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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With