I am a single developer so maintainability and code reuse are musts and using generics seems like the way to go. I am looking at Generic Entities, Generic Repositories and even Generic Controllers and I have implemented all of these into an application and tested them. I want to know is this a good way to go forward or should I be looking into creating controllers and repositories for every entity? This is the guide I followed and then I made the controller based on how I thought it would be similar https://cpratt.co/truly-generic-repository/
Base Controller:
[Produces("application/json")] public abstract class BaseController<TEntity, TResource, TUpdateResource, TSaveResource> : Controller where TEntity : Entity<int> where TResource : class { protected readonly IMapper mapper; protected readonly IRepository repository; protected IValidator<TEntity> validator; public BaseController(IMapper mapper, IRepository repository) { this.mapper = mapper; this.repository = repository; } [HttpGet] public async Task<IEnumerable<TResource>> GetAll([FromQuery] bool includeRelated) { IEnumerable<TEntity> entities = await repository.GetAllAsync<TEntity>(); return mapper.Map<IEnumerable<TEntity>, IEnumerable<TResource>>(entities); } // GET: api/Users/5 [HttpGet("{id}")] public async Task<IActionResult> Get([FromRoute] int id) { TEntity entity = await repository.GetByIdAsync<TEntity>(id); if (entity == null) return NotFound(); var entityResource = mapper.Map<TEntity, TResource>(entity); return Ok(entityResource); } // PUT: api/Users/5 [HttpPut("{id}")] public async Task<IActionResult> Put([FromRoute] int id, [FromBody] TUpdateResource updateEntity) { ValidationResult results = validator.Validate(updateEntity); if (!results.IsValid) foreach (ValidationFailure fail in results.Errors) ModelState.AddModelError(fail.PropertyName, fail.ErrorMessage); if (!ModelState.IsValid) return BadRequest(ModelState); TEntity entity = await repository.GetByIdAsync<TEntity>(id); mapper.Map(updateEntity, entity); repository.Update(entity); await repository.SaveAsync(); entity = await repository.GetByIdAsync<TEntity>(id); TResource entityResource = mapper.Map<TEntity, TResource>(entity); return Ok(entityResource); } // POST: api/Users [HttpPost] public async Task<IActionResult> Post([FromBody] TSaveResource resource) { ValidationResult results = validator.Validate(resource); if (!results.IsValid) foreach (ValidationFailure fail in results.Errors) ModelState.AddModelError(fail.PropertyName, fail.ErrorMessage); if (!ModelState.IsValid) return BadRequest(ModelState); var entity = mapper.Map<TSaveResource, TEntity>(resource); return Ok(entity); repository.Create(entity); await repository.SaveAsync(); return CreatedAtAction("GetById", new { id = entity.Id }, entity); } // DELETE: api/Users/Remove/5 [HttpDelete("Remove/{id}")] public async Task<IActionResult> Remove([FromRoute] int id) { var entity = await repository.GetByIdAsync<TEntity>(id); if (entity == null) return NotFound(); repository.Remove(entity); await repository.SaveAsync(); return Ok(entity); }
I already noticed that Authorization was going to be a problem and trying to make the class Employee the base off the IdentityUser and also the Entity class isn't going to work. Is this actually a way that a ASP.net core application can go? Is going to cause problems down the line and cost more time than it saves?