【问题标题】:MVC Attribute Routing RoutePrefix does not work with default routingMVC 属性路由 RoutePrefix 不适用于默认路由
【发布时间】:2021-07-14 20:55:13
【问题描述】:

我有一个解决方法,但我真的很想知道为什么这在 MVC 中似乎不起作用。 (.Net 4.6.1)

我有一个控制器,我想使用 RoutePrefix:

[RoutePrefix("entry")]
public class DefaultController : Controller
{
    [HttpGet]
    [Route(), Route("Index")]
    public ActionResult Index()
    {
        // ...
    }
}

在路由配置中:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapMvcAttributeRoutes();

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "entry", action = "index", id = UrlParameter.Optional }

问题在于,使用此配置,在本地 IIS 下运行进行测试,导航到“localhost/testApp/entry”有效,“localhost/testApp/entry/index”有效,但是默认的“localhost/testApp/”结果在 404 中。

这一直让我头疼,因为在一个带有默认控制器且默认设置为“home”和“index”的新项目中,“localhost/testApp”会毫无问题地呈现 Home/Index。

我将其缩小到RoutePrefix 是问题所在。如果我删除 RoutePrefix 并将默认值更改为:new { controller = "default", action = "index", id = UrlParameter.Optional }

然后“localhost/testApp”可以工作,但显然这需要对其他路由使用 /default 而不是 /entry。

另外,如果我保留前缀(将默认控制器切换回“entry”)并将Route("~/") 添加到Index 方法中,那么“localhost/testApp”也可以根据文档中的a ~ route 覆盖路由前缀。

我想知道是否有解释为什么 RoutePrefix 似乎与默认路由不兼容?我可以为该默认操作添加一个 ~/ 路由,但我似乎对 RoutePrefix 的使用方式有所了解。

【问题讨论】:

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


    【解决方案1】:

    动作属性路由具有最高优先级。如果您使用它,只有路由属性会起作用,其他所有内容都将被忽略。您可以根据需要执行任意多条路线。

    由于您有 2 个变体 - Route() 和 Route("Index") 它仅适用于 2 个 url -"localhost/testApp/entry" 和 "localhost/testApp/entry/index"。

    如果您删除 Route(),它将仅适用于一个 url-lcalhost/testApp/entry/index"。

    如果您添加 3rd Route("~/") 它将适用于 3rd url "localhost/testApp" 符号 ~ 表示任何前缀都应该被忽略,它从根开始。

    所以你不能在索引操作上使用默认的常规路由,因为它只服从路由属性。

    此外,您还有一个控制器 [RoutePrefix("entry")] 属性路由,它是下一个最高优先级,因此它会覆盖配置文件中的约定路由。这就是为什么默认路由不适用于此控制器并且它不会自动转到索引的原因。要使默认路由正常工作,您需要删除路由前缀并修复 Web 配置

    defaults: new { controller = "default", action = "index", id = UrlParameter.Optional }
    

    当前的默认控制器 = "entry" 根本不存在。

    因此,您有两种选择将索引作为默认路由操作 - 删除所有属性路由并丢失所有其他额外路由或添加更多。

    【讨论】:

    • 这与我观察到的一致,但我想问题是为什么使用该设置“默认值:”为“入口/索引”设置的默认路由设置不会当“/entry/index”是配置的路由时似乎被考虑?如果我依赖约定路由(使用EntryController)默认说“如果没有指定,请转到/entry/index”)我的前缀路由确实支持/条目/索引但在 404 中解析默认结果。
    • 这只是重申了我已经想出的解决方法,我正在寻找帮助追踪的解释是 为什么 默认路由(在 AttributeRouting 之后声明,如文档它应该是)无法解析 RoutePrefixed 路由? entry/index 是带有前缀的有效路由,但是为什么“默认值”不能解决呢? (与强制该操作路线映射到 Root 的解决方法相反)。我找不到任何说明“默认值”的文档只能适用于基于约定/配置的路由。只要在MapMvcAttributeRoutes之后声明配置,属性和配置路由就可以一起工作
    • @StevePy 对不起,我不是教授,我是一个务实的人。我只是想解释一下,即使您删除所有属性,默认路由也永远不会起作用,因为当前默认控制器“条目”不存在。前缀名称它不是新的控制器名称。索引仅适用于家庭控制器
    • 不,是的,你确实帮我弄清楚了发生了什么。即:“前缀名称它不是新的控制器名称”我做了更多的挖掘并应用了 [Route ] 到一个动作有效地从控制器/动作映射中完全排除它,即使有匹配的前缀。只有 `[Route("Index")] 没有 RoutePrefix 和 "localhost/testApp/default/index" 不起作用,只有 "localhost/testApp/index" 所以 RoutePrefix 不能替代 /controller 映射,{controller }/{action} 路由根本没有匹配到应用默认值。感谢您强调我的错误假设!
    【解决方案2】:

    感谢 Serge 帮助指出我对 [RoutePrefix] 的错误假设。这里的问题是,[RoutePrefix] 不是控制器的替代名称(尽管这就是它在表面上的行为方式),而是每个单独操作的前缀。虽然 URL 中的映射是相同的:

    示例 1:

    public class EntryController
    {
        public ActionResult Index() { ... }
    }
    

    示例 2:

    [RoutePrefix("Entry")]
    public class DefaultController
    {
        [Route("Index")]
        public ActionResult Index() { ... }
    }
    

    这两个示例都会解析“localhost/testApp/entry/index”,但是只有第一个映射会被视为匹配 {controller}/{action} 并解析“entry/index”的“默认”映射”。

    因此,如果需要将操作 /w 基于属性的路由设置为根默认值,则需要在没有 [RoutePrefix] 或 [Route("~/") 的情况下使用 [Route()] 显式声明它为根] 如果有[RoutePrefix]。因为它不会包含在 {controller}/{action} 路由中。 (通过完全删除默认 {controller}/{action} 路由进行验证)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-28
      • 2016-10-07
      • 1970-01-01
      • 1970-01-01
      • 2020-12-04
      • 2015-03-29
      • 1970-01-01
      相关资源
      最近更新 更多