C# asp.net MVC5-依赖项注入和授权属性

C# 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

我花了很长时间寻找解决我问题的办法。我有一个自定义的AuthorizeAttribute,它需要依赖于一个“服务”,该服务可以访问DbContext。 遗憾的是,依赖项注入在自定义属性中不起作用,并且始终为空

我想出了一个(对我来说)可以接受的解决办法。现在我想知道我的解决方案是否会导致不可预见的行为

Global.asax.cs

 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;
    }
}