Generic controller template implementing basic CRUD functions: - create entity from TCreateDto - read entities using List<TDto> - read entity with given id using TOneDto - update entity with given id from TCreateDto - delete entity with given id.
$ dotnet add package Crud.EFCore.TemplateGeneric controller template implementing basic CRUD functions:
TCreateDtoList<TDto>TOneDtoTCreateDtoYou will find this NuGet here.
Web API must have NuGet packages installed:
AutoMapper.Extensions.Microsoft.DependencyInjection,Microsoft.EntityFrameworkCoreand configure:
builder.Services.AddAutoMapper(Assembly.GetExecutingAssembly());
public static void AddAppDbContext(this IServiceCollection services, ConfigurationManager configuration)
{
services.AddDbContext<ApplicationDbContext>
(options => options.UseNpgsql(configuration.GetConnectionString("DbConnection")));
services.AddScoped<DbContextSeeder>();
}
using CrudCore.API.Mapping;
public class AppMappingProfile : MappingProfile
{
public AppMappingProfile() : base(Assembly.GetExecutingAssembly()) { }
}
using CrudCore.Objects;
[DisplayName("klient")]
public class Client:IIdentifiable
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual List<Order> Orders { get; set; }
}
(Optional) You could add name attribute to the entity ().
"klient"public class ClientDto : CreateClientDto
{
public int Id { get; set; }
}
public class ClientSimplyDto
{
public int Id { get; set; }
public string Name { get; set; }
}
public class CreateClientDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
}using CrudCore.API.Mapping;
public class ClientMapping : SelfMapFrom<Client>
{
protected override void CreateMaps(Profile profile)
{
profile.CreateMap<Client, ClientDto>();
profile.CreateMap<Client, ClientSimplyDto>()
.ForMember(p => p.Name, x => x.MapFrom(c => $"{c.FirstName} {c.LastName}"));
profile.CreateMap<ClientDto, Client>();
profile.CreateMap<CreateClientDto, Client>();
}
}using CrudCore.API;
using Microsoft.AspNetCore.Mvc;
[Route("api/client")]
[Authorize(Roles = RoleNames.Admin)]
public class ClientController
: EntityControllerTemplate<Client, ClientDto, ClientSimplyDto, CreateClientDto>
{
public ClientController(ApplicationDbContext context, IMapper mapper)
: base(context, mapper) { }
}And that's all!
This is the result:

You can use entity functions:
Creater to create new entity,Reader to get list of entities,Reader2 to get one entity with given id,Updater to update entity with given id,Deleter to delete entity with given id.Those functions have two methods:
public EntityFunctionTemplate<TEntity> SetEntityAction(Action<TEntity> entityAction){}
public EntityFunctionTemplate<TEntity> SetQueryableFunction(Func<IQueryable<TEntity>, IQueryable<TEntity>> includeFunc){}The SetEntityAction method validate the entity:
Creator.SetEntityAction(ValidateNewEntity);
private void ValidateNewEntity(Product entity)
{
var duplicate = _set.FirstOrDefault(
p => p.Name.ToLower() == entity.Name.ToLower() && p.Quality == entity.Quality);
if (duplicate != null)
{
throw new CustomException($"Produkt o nazwie ${entity.Name} istnieje już w bazie danych!");
}
duplicate = _set.FirstOrDefault(p => p.Code == entity.Code && p.Quality == entity.Quality);
if (duplicate != null)
{
throw new CustomException($"Produkt o kodzie ${entity.Code} istnieje już w bazie danych!");
}
}The SetQueryableFunction method manipulate the entitys set:
Reader.SetQueryableFunction((entities) => entities.Include(p => p.ProductAmounts));The EntityControllerTemplate class has endpoints:
[HttpPost]
public virtual async Task<int> AddNew([FromBody] TCreateDto dto)
=> await Creator.AddEntity(dto);
[HttpGet]
public virtual async Task<List<TDto>> GetAll()
=> await Reader.GetDtos<TDto>();
[HttpGet("{id}")]
public virtual async Task<TOneDto> GetDtoById(int id)
=> await Reader2.GetDtoById<TOneDto>(id);
[HttpPut("{id}")]
public virtual async Task Update(int id, [FromBody] TCreateDto dto)
=> await Updater.UpdateEntity(id, dto);
[HttpDelete("{id}")]
public virtual async Task Remove(int id)
=> await Deleter.RemoveEntity(id); [NonAction]
public override Task Remove(int id) => base.Remove(id); [AllowAnonymous]
public override Task<List<ProductDto>> GetAll() => base.GetAll();For make more customisation use the EntityCRUD class insted of the EntityControllerTemplate class.
The EntityCRUD class isn't controller, but is the container includes basic CRUD functions.
Example:
[Controller]
[Route("api/order")]
public class OrderController : EntityCRUD<Order>
{
public OrderController(ApplicationDbContext context, IMapper mapper) : base(context, mapper)
{
Reader2.SetQueryableFunction(entities => entities.Include(p => p.Products));
}
[HttpGet]
public async Task GetAll()
=> await Reader.GetDtos<OrderDto>();
[HttpGet("{id}")]
public async Task GetById(int id)
=> await Reader2.GetDtoById<OrderDetailsDto>(id);
[HttpPost]
public async Task<int> AddNew([FromBody] CreateOrderDto dto)
=> await Creator.AddEntity(dto);
}MIT license