This blog post talks about the above mentioned MVC issue for the applications built on Sitecore. If you are here and your application doesn’t have anything to do with Sitecore you probably should look at this stackoverflow post.

In a Sitecore application, a controller gets created for two reasons 1) the controller is declared in the layout rendering and 2) when an action method from controller gets called directly (for example, application is making an ajax call). Let’s look at the following code to understand how Sitecore resolves the controller creation request.

If the controllerName is SitecoreControllerName (this is set in the Sitecore.Mvc.Config) then, code will call CreateSitecoreController special method to create that controller. If the controllerName is fully qualified type name, then Sitecore will create that type via the DependencyResolver or using TypeHelper, if DependencyResolver was not set. If none of those two conditions apply, Sitecore will pass the control over to the DefaultControllerFactory.

This issue happens when there are more than one namespace with the same controller name in the application. For example, if a third party dll in your application has a controller named AccountController and your application has a controller named AccountController which was added in the layout rendering. Then the conflict will arise because the DefaultControllerFactory would not know which controller to create. This problem can be solved easily if we assign the fully qualified class name in the layout rendering controller field as shown in the following picture.

Controller Rendering setting

That covers the first scenario, where controllers action method is used for layout rendering. But, when controller action method is used to return JSONResult for an ajax call or a view directly, there is no way to declare the controller with fully qualified name. We are going to talk about the solution for that case now, i.e. scenario 2. In this case you can create a custom route class like below. You have to specifically add the namespaces in the route. This means, you are telling DefaultControllerFactory to resolve controllers only from the namespaces added in the given route.