我使用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 }
);
当我运行程序时,路径链接会生成http://localhost:55831/Customers/Edit/1/ALFKI
当我点击链接时,系统会调用“编辑”操作,但客户ID正在null
,其中 ALFKI 在网址中作为客户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为空?
答案 0 :(得分: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")
看到问题?第一条路线可以(并且将)匹配任何值的URL和0到5段的任何长度。一旦匹配,就无法尝试其后的其他路线。
您需要以某种方式约束路由,以确保某些URL可以传递到下一个尝试路由,即在您不想匹配该URL的情况下。
此外,细分可以可选,但无法更改位置。如果您传递的值为CurrentSort
,则自动表示其左侧的所有参数均为 required 。
对我来说,{page}
,{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个具有不同数量的段,所以它们不会发生冲突。但由于它们仍然如此广泛,您应该考虑使用another technique to constrain them,例如文字段或路径约束。例如:
routes.MapRoute(
name: "CustomerEditWithId",
url: "Customers/Edit/{page}/{id}",
defaults: new { controller = "Customers", action = "Edit" }
);
答案 1 :(得分:0)
应用第一条路线PageWithSort
而不是第二条路线。
请注意,路由框架不知道您用于生成URL的参数名称。它只是查看收到的字符串Customers/Edit/1/ALFKI
。
对于此字符串,第一个路径“PageWithSort”与
匹配因为将使用第一个匹配的路由,所以此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的硬编码部分将使其与其他路由区分开(假设没有SortColumn调用“ID”)。