WebApi Filter Unity
asp.net-web-api, c#, dependency-injection, unity-container
Solution
You will need to create a custom System.Web.Http.Filters.FilterProvider (be aware that MVC has classes with the same names in a different namespace):
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);
}
}
}
Then you will need to set the filter provider at startup:
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);
You should use the above with the Unity bootstrapper for ASP.NET Web API
A similar question using attributes: ASP.NET Web API - Inject Dependencies Into ActionFilterAttribute
Since you are using the container to maintain the list of Filters then you could just register the FilterInfo directly instead of IActionFilter.
Problem
Environement : Unity and ASP.NET MVC WEBAPI I follow the sample from the webpage http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection And after to do some modifications, I find a way to inject Filter for Controler. I used this code in the boostrapper.cs ``` var container = new UnityContainer(); container.RegisterInstance<IFilterProvider>("FilterProvider", new FilterProvider(container)); container.RegisterInstance<IActionFilter>("LogActionFilter", new TraceActionFilter()); ``` I add this class 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); } } } ``` So each time a method is called by called a class which implemented Controller, I can see the code called in the class 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); } } ``` But I don't find on the web, any sample or right way permitting to do the same thing : inject filter for add the same behavior about the WebApi. The only way find is to add manually a filter by using tag, not used the dependency injection. Can you provide any help? Best regards, Alexandre [UPDATE AFTER THE FIRST ANSWER] I launch the command Install-Package Unity.AspNet.WebApi to permit to access to UnityConfig. I add in the 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); } ``` I add in the method 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); } ``` When I call the method ...api/categoriesapi/GetAll The breakPoint in TraceActionFilter is not called. any idea? I continu to search.