Reputation: 644
I have implemented a custom route (inherit from RouteBase) to have dynamic routes based on the data stored in the database. After processing, this route ends up returning RouteData containing 1) An EF entity 2) action 3) controller
All works as expected except that I would like for the controller value to be either the full type name of a controller (I allow my users to select it from the admin panel) or the word 'Auto'. If Auto is selected I use structure map to locate a controller that implements a generic Controller<TEntityType>. To do this I return with the route data an MvcRouteHandler with a custom controller factory passed into it's constructor.
After a little digging I realized that the MvcRouteHandler does not pass that controller factory to the MvcHandler that it creates therefore my custom controller factory is never called and the route always fails. I am not sure what alternatives I have if any. I think I could probably set the controller factory in general but I feel that that would be wrong as only the requests handled by my custom routes should have the custom controller factory.
Thanks in advance, John
Upvotes: 2
Views: 760
Reputation: 644
In the end the following works. The only gray point is the ReleaseController method to which the framework does not pass a RequestContext. This is ok though because all that method does is call dispose on the controller if it implements IDisposible so the default implementation is fine.
public class RouteControllerFactory : IControllerFactory
{
private readonly DefaultControllerFactory Default = new DefaultControllerFactory();
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
return (requestContext.RouteData.Values.TryGetValue("controllerfactory") as IControllerFactory ?? Default).CreateController(requestContext, controllerName);
}
public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext requestContext, string controllerName)
{
return (requestContext.RouteData.Values.TryGetValue("controllerfactory") as IControllerFactory ?? Default).GetControllerSessionBehavior(requestContext, controllerName);
}
public void ReleaseController(IController controller)
{
Default.ReleaseController(controller);
}
}
To register the controller factory just use ControllerBuilder.Current.SetControllerFactory(typeof(RouteControllerFactory));
at Application_Start
Upvotes: 1