MVC5 路由命名空间优先级

Bah*_*ere 4 c# asp.net asp.net-mvc asp.net-mvc-routing asp.net-mvc-5

在 MVC5 路由中,我需要一种情况。我有 2 个具有相同控制器名称的命名空间。我想在没有冲突的情况下在控制器之间动态选择

routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new[] { "Namespace1","Namespace2" });
Run Code Online (Sandbox Code Playgroud)

在这里,如果在两个命名空间下有 2 个具有相同名称和操作的控制器,则会出现冲突错误。我想做的是优先考虑命名空间。

如果两个命名空间都有 Home.Index 操作,我希望 Namespace1 带头而不是错误。如果namespace1 没有我希望系统检查Namespace2 的操作。

我尝试了几种方法,但我不想使用属性路由更好的架构。

我们有一个 BaseECommerce asp.net mvc 项目和继承 BaseEcommerce 项目的 UI 项目。目的是如果 UI 项目中有相同的 Controller 和 Action 使用它。否则使用基础项目。

感谢帮助。

Nig*_*888 7

您可以通过以正确的顺序注册路线来确定路线的优先级- 第一场比赛获胜。

您不能优先考虑命名空间。namespaces 字段用于指定特定路由(通常是单个命名空间)的所有命名空间。这些是特定路由将扫描控制器的命名空间集。

所以,如果你想避免相似命名的控制器之间的冲突,你需要为每个命名空间都有一个路由。但是,由于第一个匹配的路由总是获胜,为了使其工作,每个控制器操作都需要一个唯一的 URL。

routes.MapRoute(
            "Default", // Route name
            "Namespace2/{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new[] { "Namespace2.Controllers" });

routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new[] { "Namespace1.Controllers" });
Run Code Online (Sandbox Code Playgroud)

除了上述方法,还有其他方法可以使路由匹配请求 - 有关想法,请参阅此答案

请注意,您可以使用自定义路由约束来检查某个模块是否已加载到您的应用程序中,如果是,请禁用该路由。

public class ModuleNotInstalledConstraint : IRouteConstraint
{
    public bool Match(
        HttpContextBase httpContext, 
        Route route, 
        string parameterName, 
        RouteValueDictionary values, 
        RouteDirection routeDirection)
    {
        if (module is installed)
        {
            return false;
        }

        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

    routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new { _ = new ModuleNotInstalledConstraint() },
            new[] { "Namespace1.Controllers" });
Run Code Online (Sandbox Code Playgroud)

这样,如果模块可用,路由将被忽略,因此您可以使用具有完全相同签名的路由,并且当模块可用时它将被“覆盖”。但是您仍然需要指定命名空间以确保扫描不会与具有相同名称的控制器发生冲突。