【问题标题】:WebApi Filter UnityWebApi 过滤器 Unity
【发布时间】:2013-08-19 19:37:31
【问题描述】:

环境:Unity 和 ASP.NET MVC WEBAPI 我按照网页http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection中的示例进行操作 在做了一些修改之后,我找到了一种为 Controler 注入过滤器的方法。

我在 boostrapper.cs 中使用了这段代码

var container = new UnityContainer();
container.RegisterInstance<IFilterProvider>("FilterProvider", new    FilterProvider(container));
container.RegisterInstance<IActionFilter>("LogActionFilter", new TraceActionFilter());

我添加这个类FilterProvider

public class FilterProvider : IFilterProvider
{
    private IUnityContainer container;

    public FilterProvider(IUnityContainer container)
    {
        this.container = container;
    }

    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        foreach (IActionFilter actionFilter in this.container.ResolveAll<IActionFilter>())
        {
            yield return new Filter(actionFilter, FilterScope.First, null);
        }
    }
}

所以每次通过调用实现Controller的类调用方法时,我可以看到类TraceActionFilter中调用的代码。

public class TraceActionFilter : IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        filterContext.HttpContext.Trace.Write("OnActionExecuted");
        filterContext.HttpContext.Trace.Write("Action " + filterContext.ActionDescriptor.ActionName);
        filterContext.HttpContext.Trace.Write("Controller " + filterContext.ActionDescriptor.ControllerDescriptor.ControllerName);
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
                filterContext.HttpContext.Trace.Write("OnActionExecuting");
                filterContext.HttpContext.Trace.Write("Action " + filterContext.ActionDescriptor.ActionName);
                filterContext.HttpContext.Trace.Write("Controller " + filterContext.ActionDescriptor.ControllerDescriptor.ControllerName);
    }
} 

但我在网上找不到任何允许做同样事情的示例或正确方法:注入过滤器以添加关于 WebApi 的相同行为。 find 的唯一方法是使用标签手动添加过滤器,而不是使用依赖注入。 你能提供任何帮助吗?

最好的问候, 亚历山大

[第一个答案后更新] 我启动命令 Install-Package Unity.AspNet.WebApi 以允许访问 UnityConfig。 我在 global.asax 中添加

    protected void Application_Start()
    {
        Bootstrapper.Initialise();
        UnityWebApiActivator.Start();
        ConfigureApi(GlobalConfiguration.Configuration); //line added

        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }

我在方法ConfigureApi()中添加

    void ConfigureApi(HttpConfiguration config)
    {
        var unity = new UnityContainer();
        unity.RegisterType<ProductsApiController>();
        unity.RegisterType<CategoriesApiController>();

        unity.RegisterType<IProductService, ProductService>(
            new HierarchicalLifetimeManager());
        unity.RegisterType<IProductsDatabase, ProductsDatabase>(
             new HierarchicalLifetimeManager());

        unity.RegisterType<ICategorieService, CategorieService>(
            new HierarchicalLifetimeManager());
        unity.RegisterType<ICategoriesDatabase, CategoriesDatabase>(
             new HierarchicalLifetimeManager());

        unity.RegisterType<ILogProvider, ElmahProvider>(
             new HierarchicalLifetimeManager());

        unity.RegisterType<IRootController, RootController>(
            new HierarchicalLifetimeManager());

        config.DependencyResolver = new IoCContainer(unity);

        //ADDED PARTS
        var providers = GlobalConfiguration.Configuration.Services.GetFilterProviders().ToList();
        config.Services.Add(
            typeof(System.Web.Http.Filters.IFilterProvider),
            new Filter2Provider(UnityConfig.GetConfiguredContainer()));

        var defaultprovider = providers.First(p => p is System.Web.Http.Filters.ActionDescriptorFilterProvider);
        config.Services.Remove(typeof(System.Web.Http.Filters.IFilterProvider), defaultprovider);            
    }

当我调用方法时 ...api/categoriesapi/GetAll TraceActionFilter 中的断点没有被调用。

有什么想法吗?我继续搜索。

【问题讨论】:

  • 我认为你应该认真修改这个问题的标题。它读起来更像是几个单独的标签,而不是一个问题。

标签: c# asp.net-web-api dependency-injection unity-container


【解决方案1】:

您将需要创建一个自定义 System.Web.Http.Filters.FilterProvider(请注意 MVC 在不同的命名空间中具有相同名称的类):

public class UnityActionFilterProvider 
    : System.Web.Http.Filters.ActionDescriptorFilterProvider, 
      System.Web.Http.Filters.IFilterProvider
{
    private readonly IUnityContainer container;

    public UnityActionFilterProvider(IUnityContainer container)
    {
        this.container = container;
    }

    public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, 
        HttpActionDescriptor actionDescriptor)
    {
        foreach (IActionFilter actionFilter in container.ResolveAll<IActionFilter>())
        {
            // TODO: Determine correct FilterScope
            yield return new FilterInfo(actionFilter, FilterScope.Global);
        }
    }
}

然后你需要在启动时设置过滤器提供者:

var providers = 
    GlobalConfiguration.Configuration.Services.GetFilterProviders().ToList();

GlobalConfiguration.Configuration.Services.Add(
    typeof(System.Web.Http.Filters.IFilterProvider),
    new UnityActionFilterProvider(UnityConfig.GetConfiguredContainer()));

var defaultprovider = providers.First(p => p is ActionDescriptorFilterProvider);

GlobalConfiguration.Configuration.Services.Remove(
    typeof(System.Web.Http.Filters.IFilterProvider), 
    defaultprovider);

您应该将上述内容与Unity bootstrapper for ASP.NET Web API一起使用

使用属性的类似问题:ASP.NET Web API - Inject Dependencies Into ActionFilterAttribute

由于您使用容器来维护过滤器列表,因此您可以直接注册 FilterInfo 而不是 IActionFilter。

【讨论】:

  • 您好,谢谢您的建议,我按照说明进行操作,并从类似问题中寻找答案。一切都建立了,但它不起作用;我在根问题的 [更新] 部分添加了详细信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多