2013-08-19 95 views
3

環境:Unity和ASP.NET MVC WEBAPI 我遵循網頁中的示例http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection 並且在做一些修改之後,我找到了一種方法來注入Filter for Controler。WebApi過濾器Unity

我在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); 
     } 
    } 
} 

因此,每個的方法由被稱爲其實現控制器的一類稱爲時間,我可以看到使用該代碼在類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相同的行爲。 找到的唯一方法是通過使用標籤手動添加過濾器,而不是使用依賴注入。 你能提供任何幫助嗎?

最好的問候, 亞歷山大

[更新之後的第一個答案]我 啓動命令安裝,包裝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斷點不調用。

有什麼想法嗎?我繼續搜索。

+4

我認爲你應該認真地重新爲這個問題的標題。它看起來更像是一些分離標籤,而不是問題本身。 – julealgon

回答

4

您需要創建一個自定義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。

+0

嗨,感謝您的建議,我遵循指示,並從類似問題中尋找答案。一切都在建立,但這不是行得通的;我在根問題的[更新]部分添加了詳細信息。 – user2416437