Implementing IHttpControllerFactory.CreateControllerhttp://forums.asp.net/t/1770736.aspx/1?Implementing+IHttpControllerFactory+CreateControllerMon, 26 Mar 2012 19:57:17 -040017707364837540http://forums.asp.net/p/1770736/4837540.aspx/1?Implementing+IHttpControllerFactory+CreateControllerImplementing IHttpControllerFactory.CreateController <p>I am looking at the ASP.NET MVC 4 Beta version of Web API.</p> <p>What is the proper approach to implementing IHttpControllerFactory.CreateController(HttpControllerContext controllerContext, string controllerName)? The DefaultHttpControllerFactory has two interesting behaviours in addition to resolving the Type from the controllerName:</p> <p>1. It creates an HttpControllerDescriptor and attaches it to the HttpControllerContext. If you don't do this bad things happen!</p> <p>2. To create the actual instance, it calls the registered IHttpControllerActivator passing the HttpControllerContext and calls its Create method passing through the HttpControllerContext and whatever Type it has resolved. The DefaultHttpControllerActivator ends up using the DependencyResolver.GetService to get the actual instance.</p> <p>From this, should we surmise that IHttpControllerFactory is really more of a controller name -&gt; Type resolver? Should we&nbsp;write and register&nbsp;custom IHttpControllerActivators to call our IoC of choice, or should we call IoC directly from the factory implementation?</p> <p>FYI, here is my custom factory at the moment:</p> <pre class="prettyprint">public class CustomHttpControllerFactory : IHttpControllerFactory { private readonly HttpConfiguration _configuration; private DefaultHttpControllerFactory _defaultHttpControllerFactory; public CustomHttpControllerFactory(HttpConfiguration configuration) { _configuration = configuration; _defaultHttpControllerFactory = new DefaultHttpControllerFactory(configuration); } public IHttpController CreateController(HttpControllerContext controllerContext, string controllerName) { if(// some condition that means I should handle this myself) { Type controllerType = // some code to get my type controllerContext.ControllerDescriptor = new HttpControllerDescriptor(_configuration, controllerName, controllerType); var controller = controllerContext.ControllerDescriptor.HttpControllerActivator.Create( controllerContext, controllerType); controllerContext.Controller = controller; return controller; } return _defaultHttpControllerFactory.CreateController(controllerContext, controllerName); } public void ReleaseController(IHttpController controller) { if (// this is a type I am responsible for) { // do what I need to do } _defaultHttpControllerFactory.ReleaseController(controller); } }</pre> <p>You can register this in Application_Start with:</p> <pre class="prettyprint">var configuration = GlobalConfiguration.Configuration; configuration.ServiceResolver.SetService(<br /> typeof(IHttpControllerFactory),<br /> new CustomHttpControllerFactory(configuration));</pre> 2012-02-17T11:41:26-05:004837707http://forums.asp.net/p/1770736/4837707.aspx/1?Re+Implementing+IHttpControllerFactory+CreateControllerRe: Implementing IHttpControllerFactory.CreateController <p>Much like within MVC, the controller factory is responsible for finding a controller instance to handle a request. And, much like within MVC, the default implementation uses the controller activator as an implementation detail in the process: it maps a controller name into a type, and then utilitizes the activator to create the instance of the type. We separated these two behaviors primarily for DI container authors who cannot support creating arbitrary types like concrete controller types (for example, MEF will not manufacture arbitrary types).</p> <p>That said, you could certainly implement a controller factory without using the controller activator. That's up to the factory developer.</p> 2012-02-17T13:57:49-05:004837811http://forums.asp.net/p/1770736/4837811.aspx/1?Re+Implementing+IHttpControllerFactory+CreateControllerRe: Implementing IHttpControllerFactory.CreateController <p>Thanks Brad. Are you able to address the specific question of contract? i.e. What must or should implementers do in addition to returning the instance?</p> <p>It looks like we should&nbsp;be creating and attatching the HttpControllerDescriptor to the controllerContext? Is this right, and is there anything else that should be done?</p> 2012-02-17T14:57:56-05:004839911http://forums.asp.net/p/1770736/4839911.aspx/1?Re+Implementing+IHttpControllerFactory+CreateControllerRe: Implementing IHttpControllerFactory.CreateController <p>Yes, that is currently part of the contract, though it's not obvious right now.</p> 2012-02-19T19:01:54-05:004899046http://forums.asp.net/p/1770736/4899046.aspx/1?Re+Implementing+IHttpControllerFactory+CreateControllerRe: Implementing IHttpControllerFactory.CreateController <p>I have a question about Areas. Will you include the Areas support into DefaultHttpControllerFactory? Because, I think it will be very useful. For now, to implement this functionality you have to rewrite HttpControllerFactory from scratch.</p> 2012-03-26T09:08:55-04:004900130http://forums.asp.net/p/1770736/4900130.aspx/1?Re+Implementing+IHttpControllerFactory+CreateControllerRe: Implementing IHttpControllerFactory.CreateController <p>This answered <a href="http://forums.asp.net/post/4898557.aspx">my question</a>, as well. Thanks!</p> 2012-03-26T17:29:00-04:004900354http://forums.asp.net/p/1770736/4900354.aspx/1?Re+Implementing+IHttpControllerFactory+CreateControllerRe: Implementing IHttpControllerFactory.CreateController <p>I've created a post about how to implement the HttpControllerFactory to support Areas:</p> <p><a href="http://netmvc.blogspot.com/2012/03/aspnet-mvc-4-webapi-support-areas-in.html">http://netmvc.blogspot.com/2012/03/aspnet-mvc-4-webapi-support-areas-in.html</a></p> <p>And now i can just specify area name in MapHttpRoute in the Global.asax file:</p> <p>routes.MapHttpRoute(<br> name: &quot;DefaultApi&quot;,<br> routeTemplate: &quot;api/{area}/{controller}/{id}&quot;,<br> defaults: new { id = RouteParameter.Optional }<br> );</p> 2012-03-26T19:57:17-04:00