1.0.0-beta.408

Former-commit-id: 9351510c2f675ac4be34739de73f99ef27d219aa
TangShanKaiPing
wanggang 5 years ago
parent 993142a71a
commit af723eed68

@ -3,11 +3,14 @@ using System.ComponentModel.DataAnnotations;
namespace Infrastructure.Application.Entites.Settings
{
[Display(Name = "配置")]
public class Setting : BaseEntity
{
[Required]
public string Name { get; set; }
public string Value { get; set; }
public SettingType Type { get; set; }
}
}

@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations;
namespace Infrastructure.Application.Models
{
[Display(Name = "属性")]
[Display(Name = "配置")]
public class EditSettingModel : EditModel
{
[Display(Name = "属性名称")]

@ -2,7 +2,7 @@
@using System.Security.Claims
@model PagedList<Setting>
@{
HtmlTitle = "置";
HtmlTitle = "置";
var start = 0;
var entityName = "Setting";
var hasPermissions = (User.Identity as ClaimsIdentity).Claims.Any(o => o.Value.EndsWith($"-{entityName}"));

@ -5,6 +5,7 @@
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<Version>1.0.0-beta.408</Version>
</PropertyGroup>
<ItemGroup>

@ -46,7 +46,7 @@
}
<div class="card">
<div class="card-body">
<div class="card-body" style="overflow-x:scroll;">
<table class="table table-striped projects">
<tr>
<th><input type="checkbox" class="select_all" /></th>

@ -8,6 +8,7 @@ using Infrastructure.Office;
using Infrastructure.Security;
using Infrastructure.UI;
using Infrastructure.Web.Authentication.Cookies;
using Infrastructure.Web.Mvc;
using Infrastructure.Web.Mvc.ModelBinding.Metadata;
using Infrastructure.Web.SignalR;
using Microsoft.AspNetCore.Authentication.Cookies;
@ -105,19 +106,24 @@ namespace Infrastructure.Web
//https://github.com/aspnet/Entropy/blob/master/samples/Localization.StarterWeb/Startup.cs
services.AddLocalization(options => options.ResourcesPath = null);
//https://yetawf.com/BlogEntry/Title/AdditionalMetadataAttribute%20Anyone/?BlogEntry=1005
services.AddMvc(o => o.ModelMetadataDetailsProviders.Add(new AdditionalMetadataProvider()))
.SetCompatibilityVersion(CompatibilityVersion.Latest)
.AddNewtonsoftJson()
.AddControllersAsServices()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization(options =>
services.AddMvc(o =>
{
o.ModelMetadataDetailsProviders.Add(new AdditionalMetadataProvider());
o.Conventions.Add(new GenericControllerRouteConvention());
}).ConfigureApplicationPartManager(m => m.FeatureProviders.Add(new GenericTypeControllerFeatureProvider()))
.SetCompatibilityVersion(CompatibilityVersion.Latest)
.AddNewtonsoftJson()
.AddControllersAsServices()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization(options =>
{
options.DataAnnotationLocalizerProvider = (type, factory) =>
{
options.DataAnnotationLocalizerProvider = (type, factory) =>
{
var localizer = factory.Create("Resources.Resource", Assembly.GetEntryAssembly().FullName);
return localizer;
};
});
var localizer = factory.Create("Resources.Resource", Assembly.GetEntryAssembly().FullName);
return localizer;
};
});
services.AddApiVersioning(o =>
{
o.ReportApiVersions = true;

@ -0,0 +1,15 @@
using System;
namespace Infrastructure.Web.Mvc
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class GeneratedControllerAttribute : Attribute
{
public GeneratedControllerAttribute(string route = null)
{
Route = route;
}
public string Route { get; set; }
}
}

@ -0,0 +1,322 @@
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<T> : BaseController where T : BaseEntity
{
protected readonly IRepository<T> _repo;
public GenericController(IRepository<T> repo)
{
this._repo = repo;
}
//[Route("")]
//[Route("Index")]
[HttpGet]
public virtual IActionResult Index(PagedListModel<T> 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<T>();
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<T>();
this.ToDisplayModel(entity, model);
return Result(model);
}
[HttpGet]
public virtual IActionResult Add()
{
var model = Activator.CreateInstance<T>();
this.ToEditModel(null, model);
return View(model);
}
[HttpPost]
public virtual IActionResult Add(T model)
{
if (ModelState.IsValid)
{
try
{
var entity = Activator.CreateInstance<T>();
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<T>();
this.ToEditModel(entity, model);
return View(model);
}
[HttpPost]
public virtual IActionResult Edit(T 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<Guid> 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<Guid> 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<Guid> 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<T> Include(IQueryable<T> query)
{
return query;
}
[ApiExplorerSettings(IgnoreApi = true)]
public virtual IQueryable<T> Query(PagedListModel<T> model, IQueryable<T> 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") ? Json(model) as IActionResult : View(model);
}
}
}

@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using System.Reflection;
namespace Infrastructure.Web.Mvc
{
public class GenericControllerRouteConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
if (controller.ControllerType.IsGenericType)
{
var genericType = controller.ControllerType.GenericTypeArguments[0];
var customNameAttribute = genericType.GetCustomAttribute<GeneratedControllerAttribute>();
if (customNameAttribute != null)
{
controller.ControllerName = genericType.Name;
//controller.Selectors.Add(new SelectorModel
//{
// AttributeRouteModel = new AttributeRouteModel(new RouteAttribute(customNameAttribute.Route ?? $"Entity/[controller]/[action]")),
//});
}
}
}
}
}

@ -0,0 +1,24 @@
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Controllers;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Infrastructure.Web.Mvc
{
public class GenericTypeControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
{
var currentAssembly = Assembly.GetEntryAssembly();
var candidates = currentAssembly.GetExportedTypes().Where(x => x.GetCustomAttributes(typeof(GeneratedControllerAttribute), false).Any()).ToList();
foreach (var candidate in candidates)
{
feature.Controllers.Add(
typeof(GenericController<>).MakeGenericType(candidate).GetTypeInfo()
);
}
}
}
}

@ -1,4 +1,5 @@
using Infrastructure.Domain;
using Infrastructure.Web.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
@ -6,8 +7,10 @@ using System.ComponentModel.DataAnnotations;
namespace Application.Domain.Entities
{
[Display(Name = "用户")]
[GeneratedController]
public class User : BaseEntity, ISoftDeleteEntity, IVersionEntity
{
[Display(Name = "用户名")]
public string UserName { get; set; }
public string SecurityStamp { get; set; }
@ -15,43 +18,67 @@ namespace Application.Domain.Entities
public string PasswordHash { get; set; }
public bool PasswordConfirmed { get; set; }
[Display(Name = "邮箱")]
public string Email { get; set; }
[Display(Name = "邮箱已认证")]
public bool EmailConfirmed { get; set; }
public bool PhoneNumberConfirmed { get; set; }
[Display(Name = "手机号")]
public string PhoneNumber { get; set; }
[Display(Name = "手机已认证")]
public bool PhoneNumberConfirmed { get; set; }
[Display(Name = "支付密码")]
public string PayPassword { get; set; }
[Display(Name = "支付密码已认证")]
public bool PayPasswordConfirmed { get; set; }
[Display(Name = "真实姓名")]
public string RealName { get; set; }
[Display(Name = "身份证号")]
public string IdCardNumber { get; set; }
[Display(Name = "已实名认证")]
public bool IdentityConfirmed { get; set; }
[Display(Name = "昵称")]
public string NickName { get; set; }
[Display(Name = "头像")]
public string Avatar { get; set; }
[Display(Name = "人脸识别")]
public string FaceImage { get; set; }
[Display(Name = "性别")]
public Sex Sex { get; set; }
[Display(Name = "生日")]
public DateTime? Birthday { get; set; }
[Display(Name = "可用余额")]
public decimal AvailBalance { get; set; }
[Display(Name = "冻结余额")]
public decimal FrozenBlance { get; set; }
[Display(Name = "积分")]
public long Point { get; set; }
[Display(Name = "启用登录锁定")]
public bool LockoutEnabled { get; set; }
[Display(Name = "登录失败次数")]
public int AccessFailedCount { get; set; }
[Display(Name = "锁定截止时间")]
public DateTimeOffset? LockoutEnd { get; set; }
public string RowVersion { get; set; }
public List<UserRole> UserRoles { get; set; } = new List<UserRole>();
public List<UserDepartment> UserDepartments { get; set; } = new List<UserDepartment>();

Loading…
Cancel
Save