使用Autofac将依赖项注入自定义Web API操作过滤器属性

Moh*_*and 19 asp.net-mvc dependency-injection autofac action-filter asp.net-web-api

我正在尝试解决我的自定义依赖项AuthorizeAttribute,我用它来装饰MVC4应用程序中的API控制器.问题是我不断获得NullReferenceException我在自定义过滤器中使用的服务依赖项.这是我的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

和我的自定义授权过滤器:

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
     }
}
Run Code Online (Sandbox Code Playgroud)

根据官方文档,所需要的只是:

var builder = new ContainerBuilder();
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
Run Code Online (Sandbox Code Playgroud)

但这似乎也没有成功.感谢任何帮助.

Toa*_*yen 24

您应该为属性配置属性注入

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public IAuthenticationSvc AuthenticationSvc { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

和建设者

builder.RegisterType<MyAuthorizeAttribute>().PropertiesAutowired();
Run Code Online (Sandbox Code Playgroud)

  • 我认为这个答案可能会奏效,但这不是正确的答案.因为'AuthorizeAttribute'和webApi中的完全过滤器有一个实例,如果你有同时请求它可能会产生一些问题.实际上,它不是一个线程安全的解决方案.我对吗? (3认同)

Mar*_*bec 18

我认为Autofac的文档为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();
  }
}
Run Code Online (Sandbox Code Playgroud)

它不是"纯DI",因为它使用服务定位器,但它很简单,适用于请求范围.您无需担心为每个WebApi控制器注册特定的操作过滤器.

资料来源:http: //autofac.readthedocs.io/en/latest/integration/webapi.html#provide-filters-via-dependency-injection

  • 我不得不说我更喜欢这个而不是财产注入。 (2认同)
  • 它很容易理解,但如果你打算编写测试,属性注入是一个更容易的解决方案. (2认同)

小智 15

除了@Toan Nguyen的回答,如果你有这个......

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public IAuthenticationSvc AuthenticationSvc { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

......看来你还需要(或可能需要)下面的第一行:

builder.RegisterFilterProvider();
builder.RegisterType<MyAuthorizeAttribute>().PropertiesAutowired();
Run Code Online (Sandbox Code Playgroud)

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