//Filters Using IoC and Property Injection
//A resolver needs to be implemented to build up filters with the Web Api config when the filter has IoC dependent objects.
//Firstly add Unity Web API Bootstrapper to your project.
//Now create an ActionDescriptorFilterProvider class which implements the IFilterProvider interface. This will be used to resolve the ActionFilters.
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Microsoft.Practices.Unity;
namespace WebApi2Attributes.App_Start
{
public class WebApiUnityActionFilterProvider : ActionDescriptorFilterProvider, IFilterProvider
{
private readonly IUnityContainer container;
public WebApiUnityActionFilterProvider(IUnityContainer container)
{
this.container = container;
}
public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
var filters = base.GetFilters(configuration, actionDescriptor);
var filterInfoList = new List<FilterInfo>();
foreach (var filter in filters)
{
container.BuildUp(filter.Instance.GetType(), filter.Instance);
}
return filters;
}
public static void RegisterFilterProviders(HttpConfiguration config)
{
// Add Unity filters provider
var providers = config.Services.GetFilterProviders().ToList();
config.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider), new WebApiUnityActionFilterProvider(UnityConfig.GetConfiguredContainer()));
var defaultprovider = providers.First(p => p is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(System.Web.Http.Filters.IFilterProvider), defaultprovider);
}
}
}
//Register the new filter provider in the WebApiConfig in the App_Start
using System.Web.Http;
using Microsoft.Practices.Unity.WebApi;
using WebApi2Attributes.App_Start;
namespace WebApi2Attributes
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
// Web API routes
config.MapHttpAttributeRoutes();
WebApiUnityActionFilterProvider.RegisterFilterProviders(config);
}
}
}
//Now an attribute can be defined which uses Property Injection. Construction Injection cannot be used because the attribute requires a default constructor. The Dependency attribute from Unity requires that the property is not private.
using System.Diagnostics;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Microsoft.Practices.Unity;
namespace WebApi2Attributes.Attributes
{
public class PropertyInjectionDebugActionWebApiFilter : ActionFilterAttribute
{
[Dependency]
internal IDummyBusinessClass MyDummyBusinessClass { get; set; }
public override void OnActionExecuting(HttpActionContext actionContext)
{
Debug.WriteLine("ACTION 1 DEBUG pre-processing logging and IoC:" + MyDummyBusinessClass.GetSomething());
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var objectContent = actionExecutedContext.Response.Content as ObjectContent;
if (objectContent != null)
{
var type = objectContent.ObjectType; //type of the returned object
var value = objectContent.Value; //holding the returned value
}
Debug.WriteLine("ACTION 1 DEBUG OnActionExecuted Response " + actionExecutedContext.Response.StatusCode.ToString());
}
}
}
//The Unity objects need to be registered with Unity. This is done in the App_Start/UnityConfig class.
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IDummyBusinessClass, DummyBusinessClass>();
container.RegisterType<PropertyInjectionDebugActionWebApiFilter>();
}
//Now the property injection attribute can be used in the controller.
[PropertyInjectionDebugActionWebApiFilter]
[RouteAttribute("test6")]
[AcceptVerbs("GET")]
[ActionEditDataDebugActionWebApiFilter]
public IEnumerable<string> PropertyInjectionAttributeActionsDebugAttribute()
{
return new string[] { "value1" };
}