使用ID或操作名称的ASP.NET MVC路由

5

我有一个名为“顾客(Customers)”的ASP.Net应用程序。该区域有一个同名控制器,其中只有一个名为Index的方法。

我定义了以下路由:

context.MapRoute(null,
    "Customers/{controller}/{action}",
    new { controller = "customers", action = "Index" }
);

这使我能够使用以下URL导航到我的Customers控制器上的index方法。

MyDomain/Customers

在我的客户区域中,我还有另一个名为products的控制器。这个控制器有许多方法,允许我使用产品实体(目前大多数是由Visual Studio自动生成的)。

使用当前路由,我可以使用以下URL导航到products控制器:

MyDomain/Customers/Products(显示产品控制器的索引页面)MyDomain/Customers/Products/Create(显示添加新产品的页面)。 MyDomain/Customers/Products/Details?id=1234(显示id为1234的产品)

现在我想要做的是使用更加用户友好的URL导航到详细信息页面,例如:

MyDomain/Customers/Products/1234

我定义了一个新路由,看起来像这样:

context.MapRoute(null,
    "Customers/Products/{id}",
    new { controller = "Products", action = "Details" }
    );

在我展示的第一个路由之前定义了路由。这使我能够按照我的意愿导航到产品页面,但我不能再导航到我的产品控制器上的其他方法。
例如,以下URL:
MyDomain/Customers/Products/Create 会给我以下错误信息:
参数字典包含非空类型'System.Int32'的参数'id'的空条目,用于方法'System.Web.Mvc.ViewResultDetails(Int32)'
如果我改变路由的顺序,那么我可以导航到我的产品控制器上的所有方法,但是我的详细信息URL将恢复到具有查询参数的旧格式。
如果我更新路由以看起来像这样:
context.MapRoute(null,
    "Customers/Products/{id}",
    new { controller = "Products", action = "Details", id = UrlParameter.Optional }
    );

我仍然遇到同样的问题。

有人可以告诉我如何构建我的路由以获得想要的结果吗? 简而言之:

  1. 如果我导航到“客户”区域,我希望我的URL看起来像“MyDomain/Customers”
  2. 如果我导航到产品详细信息页面,我希望我的URL看起来像“MyDomain/Customers/Products/1234”。
  3. 如果我导航到任何其他产品页面,我希望我的URL看起来像“MyDomain/Customers/Products/Create”
4个回答

4

如果ID始终是int类型,您可以像这样为路由添加约束:

context.MapRoute(null,
                 "Customers/Products/{id}",
                 new {controller = "Products", action = "Details", id = UrlParameter.Optional},
                 new {id = @"\d+"} // Constraint to only allow numbers
                );

你没有回答他的问题。他想要导航到 Customer/Products/1234 而不是 Customer/Products/Detail/1234 - Tomas Jansson
@TomasJansson 我已经更新了我的答案,因为我最初认为他的请求是不可能的。 - Richard Dalton
好的,从下降变成上升了 :) - Tomas Jansson

1

尝试类似这样的东西:

public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
        "Products_Details",
        "Customers/Products/{id}",
        new { controller="Products", action="Details" },
        new { id = @"\d+" }
    );

    context.MapRoute(
        "Customers_default",
        "Customers/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional }
    );
}

更新:添加了路由限制。

解释:第一个路由映射到您的详细信息页面,并强制用户提供格式为数字的 ID(第一个 MapRoute 中的最后一个参数)。如果 ID 没有格式 \d+,它将不匹配路由,将使用默认值。这将给您以下路由:

Customers\Products (index)
Customers\Products\1234 (details of 1234)
Customers\Products\Create (create page for products)
Customers\Products\Edit\1234 (edit page for 1234)

请问您能解释一下您的第一个路由中默认参数'detail="Index"'的含义吗?因为我以前从未见过这样的路由。 - Benjamin Gale
@Benjamin,当然...那是一个打字错误 :) (我已经修复了它) - Tomas Jansson

0
如果您想保留现有的路由,请尝试执行以下操作:
context.MapRoute(null,
     "Customers/Products/{id}", // id is optional, so Customers/Products might reasonably return all products
     new { controller = "Products", action = "Details", id = UrlParameter.Optional },
     new {id = @"\d+"} // must be numeric if present
);

context.MapRoute(null,
     "Customers/Products/{action}/{id}", // Id is optional, so this needs an action.
     new { controller = "Products", action = "Details", id = UrlParameter.Optional }
     // maybe the id is not numeric for all actions? I don't know so I won't constrain it.
);

context.MapRoute(null,
     "Customers/{controller}/{action}", // Default Customers route
     new { controller = "customers", action = "Index" }
);

前两个处理类似于/Customers/Products/...的URL,其中包含一个或两个其他部分,而最后一个处理以/Customers/开头的任何其他内容。


尝试访问“Customers/Products/Create”时,仍会导致相同的错误。 - Richard Dalton

0

试一下

    context.MapRoute(
                    "Customers_Products",
                    "Customers/Products/{productId}",
                    new { controller = "Products", action = "Details", productId= UrlParameter.Optional }
                );

    context.MapRoute(null,
                    "Customers/{controller}/{action}",
                     new { controller = "customers", action = "Index" }
);

如果你看到很多人已经提供了你想要提供的答案,那么回答就没有意义,除非你在答案中添加一些额外的内容。此外,由于“Customers/Products”将匹配第一个路由,因此您将遇到一些路由问题。 - Tomas Jansson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接