我正在Asp.net Core 2.1(EF,MVC,SQL Server)中做一个项目,通常我正在做类似以下的事情来获取当前用户(即所有者)的记录:
[HttpPost]
[Authorize]
public JsonResult GetOrders()
{
string userId = _userManager.GetUserId(User);
var applicationDbContext = _context.Order
.Where(m => m.UserID == userId);
...etc...
}
但是,我想知道是否有一种更广泛的(对于控制器,甚至是更全局的)结果过滤器,而不是必须在每个方法中包括上面的代码?
我很不高兴尝试了这个
public OrderController(ApplicationDbContext context, IAuthorizationService authorizationService, UserManager<IdentityUser> userManager)
{
_authorizationService = authorizationService;
_userManager = userManager;
string userId = _userManager.GetUserId(User);
_context = context.Where(m => m.UserID == userId);
}
我有点理解为什么这行不通。但是,基本上,我的整个项目将精炼到所有者,很高兴只在一个地方指定它,然后知道_context
(或ApplicationDbContext
?或其他适当方法)已经包括了所有者记录。
答案 0 :(得分:0)
请尝试使用EF Core 2.0中针对此用例引入的Global Query Filters。
答案 1 :(得分:0)
有两个部分可以满足您的要求,一个是实现Global Query Filters
,另一个是将UserId
传递给Global Query Filters
。
我建议您按照以下步骤操作:
Moidfy the DbContexxt
public class ApplicationDbContext : IdentityDbContext
{
protected virtual string CurrentUserId
{
get
{
return Users.FirstOrDefault(u => u.UserName == _contextAccessor.HttpContext.User.Identity.Name)?.Id;
}
}
private readonly IHttpContextAccessor _contextAccessor;
private readonly UserResolverService _userResolverService;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options
, IHttpContextAccessor contextAccessor
)
: base(options)
{
_contextAccessor = contextAccessor;
}
public DbSet<Order> Orders { get; set; }
private static MethodInfo ConfigureGlobalFiltersMethodInfo = typeof(ApplicationDbContext).GetMethod(nameof(ConfigureGlobalFilters), BindingFlags.Instance | BindingFlags.NonPublic);
protected override void OnModelCreating(ModelBuilder builder)
{
//Configure Query Filter
foreach (var entityType in builder.Model.GetEntityTypes())
{
ConfigureGlobalFiltersMethodInfo
.MakeGenericMethod(entityType.ClrType)
.Invoke(this, new object[] { builder, entityType });
}
base.OnModelCreating(builder);
}
protected void ConfigureGlobalFilters<TEntity>(ModelBuilder builder, IMutableEntityType entityType)
where TEntity : class
{
Expression<Func<TEntity, bool>> expression = null;
if (typeof(IEntityBase).IsAssignableFrom(typeof(TEntity)))
{
expression = e => ((IEntityBase)e).UserId == CurrentUserId;
builder.Entity<TEntity>().HasQueryFilter(expression);
}
}
}
通过下面的代码
注册IHttpContextAccessor
services.AddHttpContextAccessor();
为了集中控制UserId过滤器,我定义了IEntityBase
//IEntityBase.cs
public interface IEntityBase {
string UserId { get; set; }
IdentityUser User { get; set; }
}
//订单
public class Order: IEntityBase
{
public string Id { get; set; }
public string OrderNo { get; set; }
public string UserId { get; set; }
public IdentityUser User { get; set; }
public string Description { get; set; }
}