net injection dependency asp asp.net-mvc asp.net-web-api dependency-injection autofac action-filter

asp.net mvc - injection - Inyectar dependencias en el atributo de filtro de acción de API web personalizado con Autofac



dependency injection asp net core (4)

Estoy tratando de resolver las dependencias de mi AuthorizeAttribute personalizado que utilizo para decorar mis controladores API en una aplicación MVC4. El problema es que continúo obteniendo una NullReferenceException en la dependencia de servicio que uso dentro de mi filtro personalizado. Aquí está mi configuración de Autofac:

public static class WebApiConfig { public static void Register(HttpConfiguration config) { var builder = new ContainerBuilder(); builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerApiRequest(); builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().InstancePerApiRequest(); builder.RegisterAssemblyTypes(typeof(UserProfileRepository).Assembly) .Where(t => t.Name.EndsWith("Repository")) .AsImplementedInterfaces().InstancePerApiRequest(); builder.RegisterAssemblyTypes(typeof(IUserProfileMapper).Assembly) .Where(t => t.Name.EndsWith("Mapper")) .AsImplementedInterfaces().InstancePerApiRequest(); builder.RegisterAssemblyTypes(typeof(UserProfileSvc).Assembly) .Where(t => t.Name.EndsWith("Svc")) .AsImplementedInterfaces().InstancePerApiRequest(); builder.RegisterWebApiFilterProvider(config); var container = builder.Build(); var resolver = new AutofacWebApiDependencyResolver(container); config.DependencyResolver = resolver; } }

y mi filtro de autorización personalizado:

public class MyAuthorizeAttribute : AuthorizeAttribute { public IAuthenticationSvc _authenticationSvc; protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext) { if (!base.IsAuthorized(actionContext)) { return false; } var trueUserId = WebSecurity.CurrentUserId; if (_authenticationSvc.GetUsersRoles(trueUserId).Any(x => x == "Admin")) return true; // NullReferenceException on _authenticationSvc } }

Según los documentos oficiales, todo lo que se necesita es:

var builder = new ContainerBuilder(); builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);

Pero eso tampoco parece hacer el truco. Aprecio cualquier ayuda.


Además de configurar la inyección de propiedades, como se describe en otras respuestas, también puede resolver explícitamente las dependencias en la OnActivating llamada OnActivating .

public class MyAuthorizeAttribute : AuthorizeAttribute { private IAuthenticationSvc _authenticationSvc; public void SetAuthenticationSvc(IAuthenticationSvc svc) { this._authenticationSvc = svc; } }

Y luego registre el tipo:

builder.RegisterType<MyAuthorizeAttribute>() .OnActivating(_ => _.Instance.SetAuthenticationSvc(_.Context.Resolve<IAuthenticationSvc>()));

Nota: Puedes hacer lo mismo con una propiedad en lugar de un método. Elegí usar un método aquí solo para ilustrar que esta solución no dependía de PropertiesAutowired .


Además de la respuesta de @Toan Nguyen, si tienes esto ...

public class MyAuthorizeAttribute : AuthorizeAttribute { public IAuthenticationSvc AuthenticationSvc { get; set; } }

... parece que también necesita (o puede necesitar) la primera línea a continuación:

builder.RegisterFilterProvider(); builder.RegisterType<MyAuthorizeAttribute>().PropertiesAutowired();

Referencia: http://itprojectpool.blogspot.com.au/2014/03/autofac-di-on-action-filters.html


Creo que la documentación de Autofac ofrece una solución mucho más sencilla para los filtros de acción de WebApi.

public interface ServiceCallActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { // Get the request lifetime scope so you can resolve services. var requestScope = actionContext.Request.GetDependencyScope(); // Resolve the service you want to use. var service = requestScope.GetService(typeof(IMyService)) as IMyService; // Do the rest of the work in the filter. service.DoWork(); } }

No es "DI puro", ya que utiliza el localizador de servicios, pero es simple y funciona con el alcance de la solicitud. No necesita preocuparse por registrar un filtro de acción específico para cada controlador WebApi.

Fuente: http://autofac.readthedocs.io/en/latest/integration/webapi.html#provide-filters-via-dependency-injection


Debe configurar la inyección de propiedad para su atributo.

public class MyAuthorizeAttribute : AuthorizeAttribute { public IAuthenticationSvc AuthenticationSvc { get; set; } }

y el constructor

builder.RegisterType<MyAuthorizeAttribute>().PropertiesAutowired();