using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Dynamic; using System.Threading.Tasks; using zero.Core.Api; using zero.Core.Entities; using zero.Core.Identity; using zero.Core.Mapper; using zero.Core.Options; using zero.Web.Filters; using zero.Web.Models; namespace zero.Web.Controllers { [ZeroAuthorize] [BackofficeGenericController] [ServiceFilter(typeof(ModelStateValidationFilterAttribute))] public abstract class BackofficeController : Controller, ISupportsGenericsController { IMapper _mapper; IZeroOptions _options; IToken _token; protected IMapper Mapper => _mapper ?? (_mapper = HttpContext?.RequestServices?.GetService()); protected IZeroOptions Options => _options ?? (_options = HttpContext?.RequestServices?.GetService()); protected IToken Token => _token ?? (_token = HttpContext?.RequestServices?.GetService()); static JsonSerializerSettings JsonSettings; static JsonSerializerSettings TypedJsonSettings; static Type AppAwareType = typeof(IAppAwareEntity); static Type AppAwareShareableType = typeof(IAppAwareShareableEntity); static BackofficeController() { JsonSettings = new BackofficeJsonSerlializerSettings(false); TypedJsonSettings = new BackofficeJsonSerlializerSettings(true); } /// /// Creates a Microsoft.AspNetCore.Mvc.JsonResult object that serializes the specified data object to JSON. /// public override JsonResult Json(object data) => Json(data, false); /// /// Creates a Microsoft.AspNetCore.Mvc.JsonResult object that serializes the specified data object to JSON. /// public JsonResult Json(object data, bool typed) => Json(data, typed ? TypedJsonSettings : JsonSettings); /// /// Creates an edit model with appropriate options and permissions /// public JsonResult Edit(T data, bool typed = true, Action transform = null) where T : IZeroIdEntity { Type type = typeof(T); bool canBeShared = AppAwareShareableType.IsAssignableFrom(type); //ControllerContext.ActionDescriptor.FilterDescriptors[0]. dynamic model = new ExpandoObject(); model.Entity = data; model.Meta = new ExpandoObject(); model.Meta.Token = Token.Get(data); model.Meta.IsAppAware = AppAwareType.IsAssignableFrom(type); model.Meta.CanBeShared = canBeShared; model.Meta.CanCreate = true; model.Meta.CanCreateShared = canBeShared; model.Meta.CanEdit = true; model.Meta.CanDelete = true; transform?.Invoke(model); return Json(model, typed); } public IActionResult JsonPreviews(Dictionary items, Func transform) { IList previews = new List(); foreach (var item in items) { bool exists = item.Value != null; if (!exists) { previews.Add(new PreviewModel() { HasError = true, Icon = "fth-alert-circle color-red", Id = item.Key, Name = "@errors.preview.notfound", Text = "@errors.preview.notfound_text" }); } else { previews.Add(transform(item.Value)); } } return Json(previews); } public async Task JsonPreviews(Dictionary items, Func> transform) { IList previews = new List(); foreach (var item in items) { bool exists = item.Value != null; if (!exists) { previews.Add(new PreviewModel() { HasError = true, Icon = "fth-alert-circle color-red", Id = item.Key, Name = "@errors.preview.notfound", Text = "@errors.preview.notfound_text" }); } else { previews.Add(await transform(item.Value)); } } return Json(previews); } protected async Task As(T model) where TTarget : class, new() where T : IZeroEntity { if (model == null) { return new StatusCodeResult(404); } if (Mapper == null) { // TODO show error with help on how to inject mapper in constructor + base constructor } TTarget result = await Mapper.Map(model); if (result is ObsoleteEditModel) { ObsoleteEditModel editModel = result as ObsoleteEditModel; //model.CanEdit = } return Json(result); } protected async Task As(IEnumerable model) where TTarget : class, new() where T : IZeroEntity { if (model == null) { return new StatusCodeResult(404); } return Json(await Mapper.Map(model)); } protected async Task As(ListResult model) where TTarget : class, new() where T : IZeroEntity { if (model == null) { return new StatusCodeResult(404); } return Json(await Mapper.Map(model)); } protected async Task As(EntityResult model) where TTarget : class, new() where T : IZeroEntity { if (model == null) { return new StatusCodeResult(404); } return Json(await Mapper.Map(model)); } protected async Task Map(T model) where TTarget : class, new() { return await Mapper.Map(model); } } }