I try to combine Web API controllers ( IHttpController ) with decorators, but when I do this, the Web API throws an exception, because somehow it expects the actual implementation.
Applying decorators to controllers is a trick that I have successfully applied to MVC controllers, and I obviously would like to do the same in the web API.
I created a custom IHttpControllerActivator that allows you to allow decorated implementations of IHttpController . Here's the implementation lost:
public class CrossCuttingConcernHttpControllerActivator : IHttpControllerActivator { private readonly Container container; public CrossCuttingConcernHttpControllerActivator(Container container) { this.container = container; } public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { var controller = (IHttpController)this.container.GetInstance(controllerType);
My decorator looks like this:
public class MyHttpControllerDecorator : IHttpController { private readonly IHttpController decoratee; public MyHttpControllerDecorator(IHttpController decoratee) { this.decoratee = decoratee; } public Task<HttpResponseMessage> ExecuteAsync( HttpControllerContext controllerContext, CancellationToken cancellationToken) {
However, when I run my application and request a ValuesController , the web API throws me the following InvalidCastException :
Unable to create object of type 'WebApiTest.MyHttpControllerDecorator' for input 'WebApiTest.Controllers.ValuesController'.
Stacktrace:
at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c__DisplayClass5.<ExecuteAsync>b__4() at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)
Just as if the Web API provided us with the IHttpController abstraction, but skipped it and still depends on the implementation itself. This, of course, will be a serious violation of the principle of dependency inversion and will make abstraction completely useless. So I'm probably doing something wrong.
What I do? How can I happily decorate my API controllers?