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 = true)] [ApiController] [Route("Admin/[controller]/[action]")] public class CrudController : BaseController where TEntity : BaseEntity where TSearchModel : PagedListModel { protected readonly IRepository _repo; public CrudController(IRepository repo) { this._repo = repo; } [HttpGet] public virtual IActionResult Index(TSearchModel 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(TEntity); ViewData["ModelTypeExt"] = typeof(TDisplayModel); 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(TEditModel 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(TEditModel 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(TSearchModel model, IQueryable query) { return query; } [ApiExplorerSettings(IgnoreApi = true)] public virtual void ToEditModel(TEntity entity, TEditModel model) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void ToDisplayModel(TEntity entity, TDisplayModel model) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void ToEntity(TEditModel model, TEntity entity) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void OnEdit(TEntity entity, TEditModel model) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void OnInserted(TEntity entity) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void OnUpdated(TEntity entity) { } [ApiExplorerSettings(IgnoreApi = true)] public virtual void OnDeleted(TEntity 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(TEntity).Name}"; } else if (name == "Details") { permission = $"Read-{typeof(TEntity).Name}"; } else if (name == "Add") { permission = $"Add-{typeof(TEntity).Name}"; } else if (name == "Edit" || name == "Remove" || name == "Restore") { permission = $"Edit-{typeof(TEntity).Name}"; } else if (name == "Delete") { permission = $"Delete-{typeof(TEntity).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") ? Json(model) as IActionResult : View(model); } } }