简体   繁体   中英

Controller default namespace order MVC C#

I separated controllers and views on two project on last mvc version 5.2.6

We have many client project with same controller but sometime it need to override controllers.

I would do something like : Default controller in my library project but if we found controller in the main project take this one, kind of order for controllers.

But when I do :

ControllerBuilder.Current.DefaultNamespaces.Add("MainProject.Controllers");
ControllerBuilder.Current.DefaultNamespaces.Add("Library.Controllers");

I get an error controller is ambiguous

Updates

The Idea is to have a common controllers for all client website. Client website will contains only views but de need to override some controllers for specific client developments.

In my example I have two similar controllers. One in the Core namespace and one in Client:

namespace CustomControllerFactory.Core.Controllers
{
    public class DemoController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.CalledFrom = "Core";
            return View();
        }
    }
}

namespace CustomControllerFactory.Client.Controllers
{
    public class DemoController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.CalledFrom = "Client";
            return View();
        }
    }
}

For this I have created a custom controller factory:

public class CustomControllerFactory : IControllerFactory
{
    public IController CreateController(RequestContext requestContext, string controllerName)
    {
        var ns = MethodBase.GetCurrentMethod().DeclaringType.Namespace;
        var coreNs = $"{ns}.Core.Controllers";
        var clientNs = $"{ns}.Client.Controllers";

        //find out if core or client exists: https://stackoverflow.com/questions/8499593/c-sharp-how-to-check-if-namespace-class-or-method-exists-in-c
        var coreControllers = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                               from type in assembly.GetTypes()
                               where type.Namespace == coreNs
                               select type);

        var clientControllers = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                 from type in assembly.GetTypes()
                                 where type.Namespace == clientNs
                                 select type);

        Type controllerFullType = null;
        if (coreControllers.Any(x => x.Name == $"{controllerName}Controller"))
        {
            controllerFullType = Type.GetType($"{ns}.Core.Controllers.{controllerName}Controller");
        }
        else if (clientControllers.Any(x => x.Name == $"{controllerName}Controller"))
        {
            controllerFullType = Type.GetType($"{ns}.Client.Controllers.{controllerName}Controller");
        }
        else
        {
            throw new ApplicationException("no valid controller found");
        }

        IController controller = Activator.CreateInstance(controllerFullType) as Controller;
        return controller;
    }

    public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
    {
        return SessionStateBehavior.Default;
    }

    public void ReleaseController(IController controller)
    {
        (controller as IDisposable)?.Dispose();
    }

}

This does the following:

  1. Check if a suitable controller exists in the core namespace
  2. Check if a suitable controller exists in the client namespace
  3. If none is found throw an exception (implement fallback maybe?)
  4. Create Core if found, else create client controller

Then you have to register your factory in your global.asax:

ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM