【问题标题】:MVC RouteConfig affected the Html.ActionLink() helper methodMVC RouteConfig 影响了 Html.ActionLink() 辅助方法
【发布时间】:2016-01-14 12:11:02
【问题描述】:

在我的 MVC 项目中,我有 Item 控制器和一些动作,例如 Index

RouteConfig 包括:

  routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

在某些视图中,我使用辅助方法 Html.ActionLink("Items","Index","Item") 为索引操作创建锚点。所以锚结果的 href 将是 (/Item/Index)

现在,我需要映射以下 static URL:

/IndirectItem/索引

Item 控制器的 Index 动作,使用默认参数 (indirect = true),因此 RouteConfig 将为:

 routes.MapRoute(
                name: "IndirectItem",
                url: "IndirectItem/Index",
                defaults: new { controller = "Item", action = "Index", indirect = true  }
            );
   routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

看起来没问题,并且客户端请求已正确映射,但 Html.ActionLink("Items","Index","Item") 辅助方法产生的所有锚点都映射到 URL (/IndirectItem/Index) 而不是 (/Item/Index)。

如何在不将所有 Html.ActionLink() 更改为 Html.RouteLink() 或为原始 url 添加另一个路由的情况下解决此问题?

【问题讨论】:

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


    【解决方案1】:

    使用约束将是解决您的问题的便捷方法。

    使用以下 IndirectItem 路线代替您的路线。

    routes.MapRoute(
               name: "IndirectItem",
               url: "{staticVar}/{action}",
               defaults: new { controller = "Item", action = "Index", indirect = true},
               constraints: new { staticVar = "IndirectItem" }
            );
    

    并且您不需要对 默认 路线进行任何更改。

    对我来说很好用。

    【讨论】:

    • 非常好的解决方案。这是一个动态路由,可以应用于多个动作。谢谢。
    【解决方案2】:

    您遇到此问题是因为 Html.ActionLink 使用路由表生成 URL,并且由于 IndirectItem 路由与 Html.ActionLink("Items","Index","Item") 匹配(因为它在路由和操作链接中都指定了索引操作和项目控制器)。由第一次匹配完成的解析,因此路由注册的顺序很重要

    通过添加DefaultItem路由:

    routes.MapRoute(
         name: "DefaultItem",
         url: "Item/Index/{id}",
         defaults: new { controller = "Item", action = "Index", id = UrlParameter.Optional  }
    );
    

    在您当前的路线之前:

    routes.MapRoute(
           name: "IndirectItem",
           url: "IndirectItem/Index/,
           defaults: new { controller = "Item", action = "Index", indirect = true}
    );
    routes.MapRoute(
           name: "Default",
           url: "{controller}/{action}/{id}",
           defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
    

    应该解决问题

    另一种选择可能是创建从 Item 控制器继承的空 IndirectItem 控制器:

    public IndirectItemController : ItemController
    {
    }
    

    然后将路线更改为

    routes.MapRoute(
           name: "IndirectItem",
           url: "IndirectItem/Index/,
           defaults: new { controller = "IndirectItem", action = "Index", indirect = true}
    ); 
    

    【讨论】:

    • 我已经尝试过第一种方案,但是我发现更改的效果会很好,因为相同的场景会应用在多个控制器中。我认为第二种解决方案是一个不错的解决方案。谢谢。
    【解决方案3】:

    Omar Gohar 和 Alex Art 给出的答案具有误导性。

    您遇到的问题是 生成 URL 时您的路由不匹配。这仅仅是因为您没有提供所有路由值来在您的ActionLink 中创建匹配项。

    @Html.ActionLink("Items", "Index", "Item", new { indirect = true }, null)
    

    如果更改您的ActionLink 声明不是一个选项,您可以使用DataTokens parameter 将您的"indirect" 元数据附加到路由。

    您使用 DataTokens 属性来检索或分配与路由关联的值,这些值不用于确定路由是否与 URL 模式匹配。这些值被传递给路由处理程序,在那里它们可用于处理请求。

    routes.MapRoute(
        name: "IndirectItem",
        url: "IndirectItem/Index",
        defaults: new { controller = "Item", action = "Index" }
    ).DataTokens = new RouteValueDictionary(new { indirect = true });
    

    底线是RouteValues(如果没有由 URL 模式提供,则由默认值填充)不适用于元数据。它们是要匹配的真实数据,以使 URL 独一无二。

    当然,如果您实际上并未将 indirect 路由值用于任何事情,您可以简单地从路由中省略它。

    routes.MapRoute(
        name: "IndirectItem",
        url: "IndirectItem/Index",
        defaults: new { controller = "Item", action = "Index" }
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-03
      相关资源
      最近更新 更多