GenericCrudApiEFCore 1.1.0

.NET 5.0
The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
Install-Package GenericCrudApiEFCore -Version 1.1.0
dotnet add package GenericCrudApiEFCore --version 1.1.0
<PackageReference Include="GenericCrudApiEFCore" Version="1.1.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add GenericCrudApiEFCore --version 1.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: GenericCrudApiEFCore, 1.1.0"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install GenericCrudApiEFCore as a Cake Addin
#addin nuget:?package=GenericCrudApiEFCore&version=1.1.0

// Install GenericCrudApiEFCore as a Cake Tool
#tool nuget:?package=GenericCrudApiEFCore&version=1.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

GenericCrudApiEFCore

Generic library for easy creation of CRUD rest APIs with dotnet and EntityFrameworkCore.

<hr/>

Dependencies

<hr/>

Instalation:

This package is available through Nuget Packages: https://www.nuget.org/packages/GenericCrudApiEFCore

Nuget

Install-Package GenericCrudApiEFCore

.NET CLI

dotnet add package GenericCrudApiEFCore

<hr/>

How to use:

1. Creating Entity Models

Extend your entities from the "BaseEntity" class located in namespace "GenericCrudApiEFCore.Entities":

using System;
using System.Collections.Generic;

// Import Library
using GenericCrudApiEFCore.Entities;

// Sample Customer Entity (simple)
public class Customer : BaseEntity
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
    ...
}

// Sample enum Type
public enum EProductType
{
    FEEDSTOCK = 1,
    FINAL_PRODUCT,
    ...
}

// Sample Product Entity (with enum type property)
public class Product : BaseEntity
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public EProductType Type { get; set; }
    ...
}

// Sample Order Entity (with relationships)
public class Order : BaseEntity
{
    public Guid CustomerId { get; set; }
    public Customer Customer { get; set; }
    public List<OrderItem> Items { get; set; }
    ...
}

// Sample OrderItem Entity (with relationships)
public class OrderItem : BaseEntity
{
    public Guid OrderId { get; set; }
    public Order Order { get; set; }
    public Guid ProductId { get; set; }
    public Product Product { get; set; }
    ...
}

2. Mapping Entities

Extend your mapping classes from the "BaseEntityMap<T>" class located in namespace "GenericCrudApiEFCore.Mapping":

// Import Library
using GenericCrudApiEFCore.Mapping;

//  Simple mapping
public class CustomerMap : BaseEntityMap<Customer> {}

// Mapping Entity wuth enum type property
public class ProductMap : BaseEntityMap<Product>
{
    public override void Configure(EntityTypeBuilder<Product> builder)
    {
        base.Configure(builder);

        // use EnumConverter<T> to map the enum property
        builder.Property(t => t.Type)
            .HasConversion(EnumConverter<EProductType>());
    }
}

// Mapping multiple relationships
public class OrderMap : BaseEntityMap<Order>
{
    public override void Configure(EntityTypeBuilder<Order> builder)
    {
        base.Configure(builder);

        // simple relationship
        builder.HasOne(t => t.Customer)
            .WithMany()
            .HasForeignKey(t => t.CustomerId)
            .IsRequired();

        // list relationship
        builder.HasMany(t => t.Items)
            .WithOne()
            .HasForeignKey(t => t.OrderId)
            .IsRequired();
    }
}

// Mapping simple relationship
public class OrderItemMap : BaseEntityMap<OrderItem>
{
    public override void Configure(EntityTypeBuilder<OrderItem> builder)
    {
        base.Configure(builder);

        // simple relationship
        builder.HasOne(t => t.Product)
            .WithMany()
            .HasForeignKey(t => t.ProductId)
            .IsRequired();
    }
}

3. Creating an AppDbContext

Extend your AppDbContext classes from the "DbContext" class located in namespace "Microsoft.EntityFrameworkCore", override "OnModelCreating" method and add your Mapping classes to the modelBuilder:

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {}

    // In this sample we are using Sqlite, but you can use any database you want
    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options.UseSqlite("DataSource=app.db;Cache=Shared");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new CustomerMap());
        modelBuilder.ApplyConfiguration(new ProductMap());
        modelBuilder.ApplyConfiguration(new OrderMap());
        modelBuilder.ApplyConfiguration(new OrderItemMap());
        ...
    }
}

4. Creating the Controllers

Extend your Controllers classes from the "BaseCrudController" class located in namespace "GenericCrudApiEFCore.Controllers":

// Import Library
using GenericCrudApiEFCore.Controllers;

// Customers CRUD controller sample
public class CustomersController : BaseCrudController<Customer> {}

//  Products CRUD controller sample
public class ProductsController : BaseCrudController<Product> {}

//  Orders CRUD controller sample
public class OrdersController : BaseCrudController<Order> {}

//  OrderItems CRUD controller sample
public class OrderItemsController : BaseCrudController<OrderItem> {}

5. Configuring services

In your "Startup.cs" file, import namespace "GenericCrudApiEFCore" and in "ConfigureServices" method add the following:

/* Startup.cs */

// Import Library
using GenericCrudApiEFCore;

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        ...
  
        /* --- ADD THIS 3 LINES --- */
        services.AddDbContext<AppDbContext>();
        services.AddScoped<DbContext, AppDbContext>();
        services.AddCrud();
        /* ---------------------- */

        services.AddControllers();
        ...
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ...
    }
}

Ready to go!

Note: Before running the project, remember to create the database using migrations (or manually, if you prefer)

<hr/>

Using DTOs

This package allows you to implement "RequestDTO" templates for the Create and Update CRUD operations, along with a "ResponseDTO" for all returns:

1. Implementing "RequestDTOs"

Extend your RequestDTOs classes from the "BaseNotifiableRequestDTO<T>" class located in namespace "GenericCrudApiEFCore.DTOs" and override the "Validate" method:

// Import Library
using GenericCrudApiEFCore.DTOs;

// Lets implement a CreateDTO for Customer:
public class CustomerCreateRequestDTO : BaseNotifiableRequestDTO<Customer>
{
    // declare properties that you want for the DTO:
    public string Name { get; set; }
    public string Email { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
    ...

    public override void Validate()
    {
        // this library uses Flunt package for validation.
        // call "AddNotifications" end use the property "_contract" of
        // the base class to generate a Flunt validation contract:
        AddNotifications(
            _contract
                .IsEmail(Email, nameof(Email))
                .IsNotEmpty(Name, nameof(Name))
        );
    }
}

// Same concepts here, but is a UpdateDTO for Customer:
public class CustomerUpdateRequestDTO : BaseNotifiableRequestDTO<Customer>
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }

    public override void Validate()
    {
        AddNotifications(
            _contract
                .IsEmail(Email, nameof(Email))
                .IsNotEmpty(Name, nameof(Name))
        );
    }
}

2. Implementing "ResponseDTO"

Extend your ResponseDTO class from the "IResponseDTO<Customer><T>" interface located in namespace "GenericCrudApiEFCore.DTOs":

// Import Library
using GenericCrudApiEFCore.DTOs;

public class CustomerResponseDTO : IResponseDTO<Customer>
{
    // declare properties that you want for the DTO:
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    ...
}

3. Entering the DTO types in the controller definition

Same as previous Controller definition, but with DTO type parameters:

// Import Library
using GenericCrudApiEFCore.Controllers;

// Pay attention to the order of parameters
public class CustomersController
    : BaseCrudController<Customer, CustomerCreateRequestDTO, CustomerUpdateRequestDTO, CustomerResponseDTO>
{
}

Once again, you are ready to go!

<hr/>

Querying and Pagination

The API generated by this library has many features available like: Querying, Pagination and Nested Includes for child Entities/Lists:

Pagination samples

    GET /customers?page=2&perPage=20
    GET /customers?page=1&perPage=35

Querying samples

  • The query has to start with "$(" and ends whith ")"
  • The clauses must be separated by ";"
  • Operators:
    "=="" (Equal)
    ">="" (GreaterThanOrEqual)
    "<="" (LessThanOrEqual)
    ">>"" (GreaterThan)
    "<<"" (LessThan)
    "%="" (Contains)
    "%>"" (In) (for this option, values must be separeted by "|")
    GET /customers?where=$(email==jhondoe@gmail.com)
    GET /customers?where=$(email%=jhon;name%=jhon)
    GET /products?where=$(price>=10;type==FEEDSTOCK)
    GET /products?where=$(price<<10)

Nested Includes

You can use this if there are foreign key constraints for the related items:

    GET /orders?include=items
    GET /orders?include=items.product
    GET /orders?include=customer
    GET /orders?include=items.product&include=customer

All previous itens can be used together

    GET /orders?page=1&perPage=35&include=items.product&include=customer&where=$(customerId==<SOME_GUID>)
Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated