Busqué durante mucho tiempo una solución para mi problema. Tengo un AuthorizeAttribute personalizado que necesita una Dependencia de un "Servicio" que tiene acceso a un DbContext. Lamentablemente, la inyección de dependencia no funcionó en el AuthorizeAttribute personalizado y siempre fue nulo.
Se me ocurrió una solución (para mí) aceptable. Ahora quiero saber si mi solución puede causar un comportamiento imprevisto.
global.asax.cs
CustomAuthorizeAttribute.AuthorizeServiceFactory = () => unityContainer.Resolve<AuthorizeService>();CustomAuthorizeAttribute.cs
[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); } }AuthorizeService.cs
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()); } }¿Es esta una solución aceptable? ¿Tendré problemas desagradables en el futuro o tal vez haya una mejor manera de usar la inyección de dependencia en un AuthorizeAttribute personalizado?
Tengo un AuthorizeAttribute personalizado que necesita una Dependencia de un "Servicio" que tiene acceso a un DbContext. Lamentablemente, la inyección de dependencia no funcionó en el AuthorizeAttribute personalizado y siempre fue nulo.
Una implementación de IControllerFactory en el espacio de nombres System.Web.Mvc crea instancias de sus controladores para solicitudes web. Controller Factory usa System.Web.Mvc.DependencyResolver para resolver las dependencias en cada controlador.
Sin embargo, los ActionFilters/Attributes en la canalización de MVC no se crean desde Controller Factory, por lo que las dependencias no se resuelven mediante System.Web.Mvc.DependencyResolver . Es por eso que su dependencia siempre fue null .
Ahora, System.Web.Mvc.DependencyResolver es public y static para que pueda acceder a él usted mismo.
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()); } } Suponiendo que su UserService tiene un alcance de dependencia de WebRequest , es decir, su vida útil es One Per web request y está vinculada a la vida útil de HttpContext de una solicitud web, esto no construirá un nuevo UserService si uno se resolvió previamente o después si es la primera vez UserService se ha resuelto para la solicitud web dada.
En ASP.NET Core puede solicitar servicios fácilmente de la siguiente manera:
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; } }También puedes probar esto:
ASP.NET Web API y dependencias en el ámbito de la solicitud
public override void OnAuthorization(HttpActionContext filterContext) { var requestScope = filterContext.Request.GetDependencyScope(); _userService = requestScope.GetService(typeof(IUserService)) as IUserService; } // // Summary: // Retrieves the System.Web.Http.Dependencies.IDependencyScope for the given request // or null if not available. // // Parameters: // request: // The HTTP request. // // Returns: // The System.Web.Http.Dependencies.IDependencyScope for the given request or null // if not available. public static IDependencyScope GetDependencyScope(this HttpRequestMessage request);