MVC5路由命名空间的优先级

时间:2017-03-10 10:49:13

标签: c# asp.net asp.net-mvc asp.net-mvc-5 asp.net-mvc-routing

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

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

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

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

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

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

感谢您的帮助。

1 个答案:

答案 0 :(得分:4)

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

您无法确定名称空间的优先级。名称空间字段用于指定特定路由的所有名称空间(通常是单个名称空间)。这些是特定路由将扫描控制器的命名空间集。

因此,如果要避免类似命名控制器之间的冲突,则需要为每个命名空间建立路由。但是,由于第一个匹配路由总是获胜,因此每个控制器操作都需要一个唯一的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" });

除了上述方法之外,还有其他方法可以使路线匹配请求 - 有关提示,请参阅this answer

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

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;
    }
}

用法

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

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