【问题标题】:Controller default namespace order MVC C#控制器默认命名空间顺序 MVC C#
【发布时间】:2025-12-21 06:50:16
【问题描述】:

我在最后一个 mvc 版本 5.2.6 上分离了两个项目的控制器和视图

我们有许多具有相同控制器的客户端项目,但有时需要覆盖控制器。

我会做类似的事情: 我的库项目中的默认控制器,但如果我们在主项目中找到控制器,请使用这个控制器。

但是当我这样做时:

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

我得到一个错误控制器不明确

更新

我们的想法是为所有客户网站提供一个通用控制器。客户端网站将仅包含视图,但需要针对特定​​客户端开发覆盖一些控制器。

【问题讨论】:

  • 我们能知道你为什么需要这种东西吗?我认为,如果您更清楚地解释您试图解决的问题,我们可以找到更好或最佳的解决方案。

标签: c# asp.net-mvc


【解决方案1】:

在我的示例中,我有两个类似的控制器。一个在 Core 命名空间中,一个在 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();
        }
    }
}

为此我创建了一个自定义控制器工厂:

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://*.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();
    }

}

执行以下操作:

  1. 检查核心命名空间中是否存在合适的控制器
  2. 检查客户端命名空间中是否存在合适的控制器
  3. 如果没有找到,则抛出异常(可能实现回退?)
  4. 如果找到则创建核心,否则创建客户端控制器

然后你必须在你的 global.asax 中注册你的工厂:

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

【讨论】:

  • 谢谢,这就是我想要的,但它永远找不到我的控制器。 var ns = MethodBase.GetCurrentMethod().DeclaringType.Namespace;一片空白。正常吗?