0

我已经使用RouteLink.

@Html.RouteLink("Edit", "PageWithId",
new
{
    controller = "Customers",
    action = "Edit",
    id = item.CustomerID,
    page = ViewBag.CurrentPage
}) 

我正在将此路由PageWithId与路由链接一起使用

routes.MapRoute(
    name: "PageWithId",
    url: "{controller}/{action}/{page}/{id}",
    defaults: new { controller = "Customers", action = "Edit", page = UrlParameter.Optional, id = UrlParameter.Optional }
);

我有 3 个路由代码。这是所有

routes.MapRoute(
    name: "PageWithSort",
    url: "{controller}/{action}/{page}/{SortColumn}/{CurrentSort}",
    defaults: new { action = "Index", page = UrlParameter.Optional, SortColumn = UrlParameter.Optional, CurrentSort = UrlParameter.Optional }
);

routes.MapRoute(
    name: "PageWithId",
    url: "{controller}/{action}/{page}/{id}",
    defaults: new { controller = "Customers", action = "Edit", page = UrlParameter.Optional, id = UrlParameter.Optional }
);

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

当我运行我的程序时,路由链接会生成像这样的 URLhttp://localhost:55831/Customers/Edit/1/ALFKI

当我单击链接时,将调用编辑操作,但客户 ID 正在获取null,因为ALFKI在 URL 中作为客户 ID。

这是我的编辑操作详细信息

public ActionResult Edit(string id, int page)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Customer customer = db.Customers.Find(id);
    if (customer == null)
    {
        return HttpNotFound();
    }
    ViewBag.CurrentPage = page;
    return View(customer);
}

请告诉我为什么当ALFKI作为客户 id 传递时 id 为空?

4

2 回答 2

1

占位符(例如{page}{controller})的作用类似于变量。它可以匹配任何东西并将其存储在具有相同名称的路由值中。

因此,您对配置的实际意思是:

尝试

/<anything (optional)>/<anything (optional)>/<anything (optional)>/<anything (optional)>/<anything (optional)>

如果这不起作用,请尝试

/<anything (optional)>/<anything (optional)>/<anything (optional)>/<anything (optional)>

如果这不起作用,请尝试

/<anything (optional)>/<anything (optional)>/<anything (optional)>

如果这不起作用,因为 {id} 是可选的,请尝试

/<anything (optional)>/<anything (optional)>

如果这不起作用,因为 {action} 是可选的,请尝试

/<anything (optional)> (if it matches, action will be "Index")

如果这不起作用,因为 {controller} 是可选的

/ (if it matches, controller will be "Home" and action will be "Index")

看到问题了吗?第一个路由可以(并且将)匹配任何值和任何长度(从 0 到 5 个段)的 URL。一旦匹配,就无法尝试跟随它的另一条路线。

您需要以某种方式限制路由,以确保某些 URL 可以传递到下一个尝试的路由,即在您不想匹配该 URL 的情况下。

此外,可以将段设为可选,但不能更改位置。如果您传递的值意味着CurrentSort,它自动意味着它左侧的所有参数都是必需的。

{page}对我来说, make{SortColumn}{CurrentSort}可选的似乎不合逻辑。如果您不需要它们,则要么使用不同的路由,要么完全将它们从路径中取出并改用查询字符串(路由不受查询字符串值的影响,它们仅在路径上匹配)。

要使值成为必需值,请value = UrlParameter.Optional从默认值中删除。事实上,您可以删除所有默认值,因为控制器和操作已经在 URL 中传递。

routes.MapRoute(
    name: "PageWithSort",
    url: "{controller}/{action}/{page}/{SortColumn}/{CurrentSort}"
);

routes.MapRoute(
    name: "PageWithId",
    url: "{controller}/{action}/{page}/{id}"
);

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

尽管这些路线仍然可以匹配任何东西,但这会将它们限制为特定的长度,并且由于它们中的所有 3 个具有不同数量的段,因此它们不会发生冲突。但由于它们仍然如此广泛,您应该考虑使用另一种技术来约束它们,例如文字段或路由约束。例如:

routes.MapRoute(
    name: "CustomerEditWithId",
    url: "Customers/Edit/{page}/{id}",
    defaults: new { controller = "Customers", action = "Edit" }
);
于 2018-02-05T18:47:56.477 回答
0

应用第一条路线PageWithSort而不是第二条路线。

请注意,路由框架不知道您用于生成 URL 的参数名称。它只是查看接收到的字符串Customers/Edit/1/ALFKI

对于此字符串,第一个路由“PageWithSort”与

  • 控制器 = 客户
  • 动作 = 编辑
  • 页 = 1
  • 排序列 = ALFKI
  • CurrentSort = null (这是可以的,因为它是可选的)

因为将使用第一个匹配的路由,所以这个 URL 永远不会命中“PageWithId”路由。

也许您可以使“PageWithSort”的SortColumn和参数成为必需的?CurrentSort

或者更改定义路由的顺序。

或者为“PageWithSort”路由添加一些独特的东西,例如

routes.MapRoute(
        name: "PageWithId",
        url: "{controller}/{action}/{page}/ID/{id}",
        //                                 ^^
        defaults: new { controller = "Customers", action = "Edit", page = UrlParameter.Optional, id = UrlParameter.Optional }
    );

添加/ID为 URL 的硬编码部分将使其与其他路由区分开来(假设没有调用“ID”的 SortColumn)。

于 2018-02-05T16:03:59.973 回答