using Infrastructure.Application; using Infrastructure.Data; using Infrastructure.Domain; using Infrastructure.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; namespace Infrastructure.Web.Mvc { //[ApiExplorerSettings(IgnoreApi = false)] //[ApiController] //[Route("Entity/[controller]/[action]")] [Area("Entity")] public class GenericController : BaseController where T : BaseEntity { protected IRepository Repo { get; } public GenericController(IRepository repo) { this.Repo = repo; } //[Route("")] //[Route("Index")] [HttpGet] public virtual IActionResult Index(PagedListModel model) { if (model == null) { throw new ArgumentNullException(nameof(model)); } var query = this.Repo.ReadOnlyTable(); //if (model is ISoftDeleteEntity && !model.IsDeleted) //{ // query = query.Where(o => o.IsDeleted == null); //} query = this.Include(query); query = this.Query(model, query); model.TotalCount = query.Count(); model.List.AddRange(query.Skip(model.PageSize * (model.PageIndex - 1)) .Take(model.PageSize) .ToList() .Select(o => { var m = o.To(); this.ToDisplayModel(o, m); return m; }) .ToList()); ViewData["EntityTypeExt"] = typeof(T); ViewData["ModelTypeExt"] = typeof(T); return this.Result(model); } [HttpGet] public virtual IActionResult Details(Guid id) { var query = this.Repo.ReadOnlyTable(); query = this.Include(query); var entity = query.FirstOrDefault(o => o.Id == id); var model = entity.To(); this.ToDisplayModel(entity, model); return Result(model); } [HttpGet] public virtual IActionResult Add() { var model = Activator.CreateInstance(); this.ToEditModel(null, model); return View(model); } [HttpPost] public virtual IActionResult Add(T model) { if (ModelState.IsValid) { try { var entity = Activator.CreateInstance(); entity.From(model); this.ToEntity(model, entity); this.Repo.Add(entity); if (this.Repo.SaveChanges() > 0) { this.OnInserted(entity); } return RedirectTo(); } catch (DbUpdateException ex) { ex.PrintStack(); ModelState.AddModelError("", ex.Message); } } this.ToEditModel(null, model); return View(model); } [HttpGet] public virtual IActionResult Edit(Guid id) { var query = this.Repo.ReadOnlyTable(); query = this.Include(query); var entity = query.FirstOrDefault(o => o.Id == id); var model = entity.To(); this.ToEditModel(entity, model); return View(model); } [HttpPost] public virtual IActionResult Edit(T model) { if (model is null) { throw new ArgumentNullException(nameof(model)); } var id = (Guid)model.GetType().GetProperty("Id").GetValue(model); var query = this.Repo.Table(); query = this.Include(query); var entity = query.FirstOrDefault(o => o.Id == id); if (ModelState.IsValid) { try { this.OnEdit(entity, model); entity.From(model); this.ToEntity(model, entity); if (this.Repo.SaveChanges() > 0) { this.OnUpdated(entity); } return RedirectTo(); } catch (DbUpdateException ex) { ex.PrintStack(); ModelState.AddModelError("", ex.Message); } } this.ToEditModel(entity, model); return View(model); } [HttpPost] public virtual IActionResult Remove(List list) { if (list == null) { throw new ArgumentNullException(nameof(list)); } try { foreach (var id in list) { var query = this.Repo.Table(); var entity = query.FirstOrDefault(o => o.Id == id); entity.IsDeleted = Guid.NewGuid().ToString(); this.Repo.SaveChanges(); } return RedirectTo(); } catch (DbUpdateException ex) { ex.PrintStack(); return RedirectTo(rawMesage: ex.Message); } } [HttpPost] public IActionResult Restore(List list) { if (list == null) { throw new ArgumentNullException(nameof(list)); } try { foreach (var id in list) { var query = this.Repo.Table(); var entity = query.FirstOrDefault(o => o.Id == id); entity.IsDeleted = null; this.Repo.SaveChanges(); } return RedirectTo(); } catch (DbUpdateException ex) { ex.PrintStack(); return RedirectTo(rawMesage: ex.Message); } } [HttpPost] public virtual IActionResult Delete(List list) { if (list == null) { throw new ArgumentNullException(nameof(list)); } try { foreach (var id in list) { var query = this.Repo.Table(); var entity = query.FirstOrDefault(o => o.Id == id); this.Repo.Delete(entity); if (this.Repo.SaveChanges() > 0) { this.OnDeleted(entity); } } return RedirectTo(); } catch (DbUpdateException ex) { ex.PrintStack(); return RedirectTo(rawMesage: ex.Message); } } [ApiExplorerSettings(IgnoreApi = true)] public virtual IQueryable Include(IQueryable query) { return query; } [ApiExplorerSettings(IgnoreApi = true)] public virtual IQueryable Query(PagedListModel model, IQueryable query) { return query; } [ApiExplorerSettings(IgnoreApi = true)] public virtual void ToEditModel(T entity, T model) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void ToDisplayModel(T entity, T model) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void ToEntity(T model, T entity) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void OnEdit(T entity, T model) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void OnInserted(T entity) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void OnUpdated(T entity) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void OnDeleted(T entity) { } [ApiExplorerSettings(IgnoreApi = true)] public override void OnActionExecuting(ActionExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var name = (context.ActionDescriptor as ControllerActionDescriptor).ActionName; var permission = string.Empty; if (name == "Index") { permission = $"Read-{typeof(T).Name}"; } else if (name == "Details") { permission = $"Read-{typeof(T).Name}"; } else if (name == "Add") { permission = $"Add-{typeof(T).Name}"; } else if (name == "Edit" || name == "Remove" || name == "Restore") { permission = $"Edit-{typeof(T).Name}"; } else if (name == "Delete") { permission = $"Delete-{typeof(T).Name}"; } if (!string.IsNullOrEmpty(permission)) { var returnUrl = context.HttpContext.Request.GetUrl(); if (!context.HttpContext.User.Identity.IsAuthenticated) { context.Result = new RedirectToActionResult("Login", "Account", new { area = "", returnUrl }); ; } else if (!context.HttpContext.User.IsInRole(permission)) { context.Result = new RedirectToActionResult("AccessDenied", "Account", new { area = "", returnUrl }); } } } [ApiExplorerSettings(IgnoreApi = true)] private IActionResult Result(object model) { return this.Request.Headers["accept"].ToString().Contains("json", StringComparison.OrdinalIgnoreCase) ? Json(model) as IActionResult : View(model); } } }