using System.Linq.Expressions; using System.Reflection; using ApiSourceGeneratorHelper; using AutoMapPropertyHelper; using EntityFrameworkCore.Projectables; using EntityFrameworkCore.Projectables.Extensions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using NejCommon.Utils; using Swashbuckle.AspNetCore.Annotations; using NejCommon.Models; using System.Runtime.CompilerServices; namespace NejCommon.Controllers { public abstract class AutoController : AutoController where TType : class, new() where TRequest : IAutomappedAttribute, new() where TResponse : IAutomappedAttribute, new() { public AutoController(CommonDbContext appDb, IServiceProvider providers) : base(appDb, providers) { } } /// /// /// /// The underyling type /// The request type /// The response type [ApiController] public abstract partial class AutoController : AutoGetterController where TType : class, new() where TGetAllResponse : IAutomappedAttribute, new() where TCreateRequest : IAutomappedAttribute, new() where TCreateResponse : IAutomappedAttribute, new() where TGetResponse : IAutomappedAttribute, new() where TUpdateRequest : IAutomappedAttribute, new() where TUpdateResponse : IAutomappedAttribute, new() { public AutoController(CommonDbContext appDb, IServiceProvider providers) : base(appDb, providers) { } protected virtual TType AssociateWithParent(TType entity, TOwner comp) { var props = typeof(TType).GetProperty(HelperMainName); if (props == null) { //not implemented throw new NotImplementedException("Special parent association not implemented"); } props.SetValue(entity, comp); return entity; } /// /// Creates the /// /// /// Success /// There was an error [HttpPost] public virtual async Task, CreatedAtRoute>> Create([FromServices] TOwner company, [FromBody] TCreateRequest body) { var entity = db.Create(); entity = AssociateWithParent(entity, company); await db.AddAsync(entity); body.ApplyTo(providers, entity); return await db.ApiSaveChangesAsyncCreate(providers, entity); } /// /// Delete company. /// /// /// Success /// There was an error [HttpDelete] [Route("{id}/")] public virtual async Task, Ok>> Delete([FromServices][ModelBinder(Name = "id")] TType entity) { db.Remove(entity!); return await db.ApiSaveChangesAsync(TypedResults.Ok()); } /// /// Update company. /// /// /// /// Success /// There was an error [HttpPut] [Route("{id}/")] public virtual async Task, Ok>> Update([FromServices][ModelBinder(Name = "id")] TType entity, [FromBody] TUpdateRequest body) { body.ApplyTo(providers, entity); var dat = new TUpdateResponse().ApplyFrom(providers, entity); var res = await db.ApiSaveChangesAsyncOk(providers, entity); //use the private constructor thru reflection var ctor = typeof(Results, Ok>).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0]; return (Results, Ok>)ctor.Invoke(new object[] { res.Result }); } } [ApiController] public abstract class AutoGetterController : ControllerBase where TType : class, new() where TGetAllResponse : IAutomappedAttribute, new() where TGetResponse : IAutomappedAttribute, new() { protected readonly CommonDbContext db; protected readonly IServiceProvider providers; public AutoGetterController(CommonDbContext appDb, IServiceProvider providers) : base() { db = appDb; this.providers = providers; } protected abstract IQueryable GetQuery(TOwner comp); protected virtual IQueryable ApplyDefaultOrdering(IQueryable query) { return query; } protected virtual Task> ApplyPagination(IQueryable query, Pagination pag) { return query.ApplyPaginationRes(providers, pag); } /// /// Get all the /// /// Success /// There was an error [HttpGet] public virtual async Task, Ok>>> GetAll([FromServices] TOwner company, [FromQuery] Pagination pag) { var data = await ApplyPagination(ApplyDefaultOrdering(GetQuery(company)).AsNoTrackingWithIdentityResolution(), pag); //Console.Writeline(data.Data); return TypedResults.Ok(data); } /// /// Gets the /// /// /// Success /// There was an error [HttpGet] [Route("{id}/")] public virtual async Task>> Get([FromServices][ModelBinder(Name = "id")] TType entity) { var dat = new TGetResponse().ApplyFrom(providers, entity); return TypedResults.Ok(dat); } } }