C# asp.net MVC5-依赖项注入和授权属性
我花了很长时间寻找解决我问题的办法。我有一个自定义的AuthorizeAttribute,它需要依赖于一个“服务”,该服务可以访问DbContext。 遗憾的是,依赖项注入在自定义属性中不起作用,并且始终为空 我想出了一个(对我来说)可以接受的解决办法。现在我想知道我的解决方案是否会导致不可预见的行为 Global.asax.csC# asp.net MVC5-依赖项注入和授权属性,c#,entity-framework,dependency-injection,asp.net-mvc-5,authorize-attribute,C#,Entity Framework,Dependency Injection,Asp.net Mvc 5,Authorize Attribute,我花了很长时间寻找解决我问题的办法。我有一个自定义的AuthorizeAttribute,它需要依赖于一个“服务”,该服务可以访问DbContext。 遗憾的是,依赖项注入在自定义属性中不起作用,并且始终为空 我想出了一个(对我来说)可以接受的解决办法。现在我想知道我的解决方案是否会导致不可预见的行为 Global.asax.cs CustomAuthorizeAttribute.AuthorizeServiceFactory = () => unityContainer.Resolve
CustomAuthorizeAttribute.AuthorizeServiceFactory = () => unityContainer.Resolve<AuthorizeService>();
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public static Func<AuthorizeService> AuthorizeServiceFactory { get; set; }
public Privilege Privilege { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
return AuthorizeServiceFactory().AuthorizeCore(httpContext, Privilege);
}
}
public class AuthorizeService
{
[Dependency]
public UserService UserService { private get; set; }
public bool AuthorizeCore(HttpContextBase httpContext, Privilege privilege)
{
ApplicationUser user = UserService.FindByName(httpContext.User.Identity.Name);
return UserService.UserHasPrivilege(user.Id, privilege.ToString());
}
}
这是一个可以接受的解决方案吗?我将来会遇到棘手的问题吗?还是有更好的方法在自定义属性中使用依赖项注入
我有一个自定义属性,它需要对
可以访问DbContext的“服务”。可悲的是,这种依赖
注入在自定义属性中不起作用,并且始终无效
空
System.Web.Mvc
命名空间中的IControllerFactory
实现为Web请求创建控制器实例。控制器工厂使用System.Web.Mvc.DependencyResolver
解析每个控制器中的依赖项
但是,中的ActionFilters/属性不是从控制器工厂创建的,因此不使用System.Web.Mvc.DependencyResolver
解析依赖项。这就是为什么依赖项总是null
现在,System.Web.Mvc.DependencyResolver
是public
和static
,所以您可以自己访问它
public class AuthorizeService : AuthorizeAttribute
{
private UserService UserService
{
get
{
return DependencyResolver.Current.GetService<UserService>();
}
}
public bool AuthorizeCore(HttpContextBase httpContext, Privilege privilege)
{
ApplicationUser user = UserService.FindByName(httpContext.User.Identity.Name);
return UserService.UserHasPrivilege(user.Id, privilege.ToString());
}
}
公共类AuthorizeService:AuthorizeAttribute
{
专用用户服务用户服务
{
得到
{
返回DependencyResolver.Current.GetService();
}
}
public bool AuthorizeCore(HttpContextBase httpContext,Privilege)
{
ApplicationUser user=UserService.FindByName(httpContext.user.Identity.Name);
返回UserService.UserHasPrivilege(user.Id,privilege.ToString());
}
}
假设您的UserService
具有WebRequest的依赖范围,也就是说,它的生存期是每个web请求一个,并与web请求的HttpContext
的生存期相关联。如果之前或之后已经解决了一个UserService
,如果这是第一次为给定的web请求解决UserService
,则不会构造新的UserService
。您也可以尝试以下方法:
在ASP.NET Core中,您可以通过以下方式轻松请求服务:
public class CustomAuthAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public async void OnAuthorization(AuthorizationFilterContext context)
{
// var user = context.HttpContext.User;
// if (!user.Identity.IsAuthenticated)
// {
// context.Result = new UnauthorizedResult();
// return;
// }
var userService = context.HttpContext.RequestServices.GetService(typeof(UserService)) as UserService;
}
}
我同意这个解决方案,我也有同样的问题,上面的回答很有帮助。但由于我使用的是
Autofac
,它们提供了一种通过提供程序解决操作过滤器中的依赖关系的方法“但是使用上述提供程序时遇到的问题是,我的UserService
依赖于DbContext
,它抛出一个错误“操作无法完成,因为DbContext已被释放错误r”,仅当我在让上一个请求完成之前点击浏览器刷新按钮时,问题不是asp net core。架构上的差异太深了,这就是我提到“ASP.NET核心”的原因。我在这里添加了这个答案,因为我猜很多像我这样的人会在“ASP.NET核心”中遇到类似的问题:-)谢谢Majid。我想知道这样获得服务是否有负面影响?如果你能告诉我这里发生了什么,我将不胜感激。即使结果是我想要的,@Lukas这里发生的事情是,RequestServices
是一个类型为IServiceProvider
的属性,自动配置并设置为从IServiceCollection
在DI设置中定义并注册。(适用于ASP.NET Core的Startup.cs)。
public class CustomAuthAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public async void OnAuthorization(AuthorizationFilterContext context)
{
// var user = context.HttpContext.User;
// if (!user.Identity.IsAuthenticated)
// {
// context.Result = new UnauthorizedResult();
// return;
// }
var userService = context.HttpContext.RequestServices.GetService(typeof(UserService)) as UserService;
}
}