Why default factory WON'T return full name of the controllers (with namespaces)?
I'm using Service Locator and autofac.
using System.Web.Mvc;
using Microsoft.Practices.ServiceLocation;
namespace Application.Core.MVC
{
public override IController CreateController(System.Web.Routing.RequestContext requestContext, string **controllerName**)
{
return ServiceLocator.Current.GetInstance<IController>(controllerName);
}
}
I had two home controllers (one under area Blog)
http://localhost/Home
http://localhost/Blog/Home
controllerName return only "Home" without full qualified name for both in above code.
This creates a problem when I try to regiser controllers' names for dependency injection.
Here is how I register controllers right now according to this situation. Even this brings up the pages without exception. But When I access http://localhost/Home, both controllers invoked regardlessly.
foreach (var tp in currentAssemblyControllersTypes)
builder.Register(tp).FactoryScoped().Named(tp.Name.Replace("Controller", ""));
Anyone can help?Thanks.
The DefaultControllerFactory.CreateController() method is responsible for returning a controller for the given request. The controllerName parameter is just the {controller} part of the route. It's CreateController()'s job - not its caller's - to figure out the proper type given the controller name as specified in the URL.
To make this easier, DefaultControllerFactory.CreateController() delegates into two other methods: GetControllerType() and GetControllerInstance(). If you want to use the original controller resolution logic (e.g. type lookup) but just change how types are instantiated, leave the CreateController() and GetControllerType() methods as-is, and just override GetControllerInstance(). This already takes care of the namespace lookup logic you're duplicating and will make your code far simpler.
[Update according to Levi's answer]
1.Register each controller in full name explicitly:
foreach (var tp in currentAssemblyControllersTypes)
builder.Register(tp).FactoryScoped().Named(tp.FullName)
//Application.Controllers.HomeController
//Application.Areas.Blog.Controllers.HomeController
2 .Specify namespace in MapRoute() for Application.Controllers.HomeController in Global.ascx.cs according to PDC09 demo
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
,new string [] { "Application.Controllers"} //Specify namespace
);
}
3.Override GetControllerInstance() meothod IoCControllerFactory.cs
Protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, System.Type controllerType)
{
return (controllerType == null)? base.GetControllerInstance(requestContext,controllerType):ServiceLocator.Current.GetInstance<IController>(controllerType.FullName);
}