asp.net-mvc ASP.NET MVC Url.Action 将当前路由值添加到生成的 url
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7133223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ASP.NET MVC Url.Action adds current route values to generated url
提问by willvv
I have seen this question a couple of times here in SO but none of them with any acceptable answer:
我已经在 SO 中多次看到这个问题,但没有一个有任何可接受的答案:
ASP.NET MVC @Url.Action includes current route data
ASP.NET MVC implicitly adds route values
ASP.NET MVC @Url.Action 包含当前路由数据
ASP.NET MVC 隐式添加路由值
Basically I have Controller with an action method called Group, it has an overload that receives no parameters and displays a list of elements and another one that receives an id and displays details for that group.
基本上我有一个控制器,它有一个名为 Group 的操作方法,它有一个重载,它不接收参数并显示一个元素列表,另一个接收一个 id 并显示该组的详细信息。
If I do something like this:
如果我做这样的事情:
Url.Action("Group", "Groups");
From the main page of the site (/) it returns an url like this:
从站点的主页 (/) 返回一个像这样的 URL:
"mysite.com/Groups/Group"
which is alright Now, if the current address of the site is /Groups/Group/1 And I call the same method
没关系 现在,如果站点的当前地址是 /Groups/Group/1 并且我调用相同的方法
Url.Action("Group", "Groups");
the returned url is this:
返回的网址是这样的:
"mysite.com/Groups/Group/1"
It automatically adds the value of the route for the current page when generating the URL. Even if I generate the URL this way:
它在生成 URL 时自动添加当前页面的路由值。即使我以这种方式生成 URL:
Url.Action("Group", "Groups", null);
Thus explicitly specifying that I don't want any route values, the generated URL is the same. To get the address I want I have to explicitly set the route value to an empty string, like so:
因此明确指定我不想要任何路由值,生成的 URL 是相同的。要获取我想要的地址,我必须将路由值显式设置为空字符串,如下所示:
Url.Action("Group", "Groups", new {id=""});
This will generate the following url:
这将生成以下网址:
"mysite.com/Groups/Group"
My question is, why does this happen? If I don't set any route values it shouldn't add them to the generated URL.
我的问题是,为什么会发生这种情况?如果我没有设置任何路由值,它就不应该将它们添加到生成的 URL 中。
采纳答案by objectbox
Url.Action will reuse the current request parameters, if you do not explicitly set them. It is by design in outbound url-matching algorithm. When looking for the route data parameters in a process of generating url, parameters are taken from:
Url.Action 将重用当前的请求参数,如果你没有明确设置它们。它是在出站 url 匹配算法中设计的。在生成url的过程中查找路由数据参数时,参数取自:
1) explicitly provided values
1) 明确提供的值
2) values from the current request
2) 来自当前请求的值
3) defaults
3) 默认值
In the order I specified above.
按照我上面指定的顺序。
Outbound matching algorithm for routes is complicated, so it is good practice to explicitly set all parameters for request, as you did in your example
路由的出站匹配算法很复杂,因此像您在示例中所做的那样,显式设置请求的所有参数是一种很好的做法
回答by Valamas
My application explicitly sets route values and does not want a magical value from the current request. I want to be in full control.
我的应用程序显式设置路由值并且不希望从当前请求中获得神奇的值。我想完全控制。
I have made an extension which coexists with my route library collection. Hence the single RouteValueDictionary param. (See my Route library comment at the bottom)
我做了一个与我的路线库收藏共存的扩展。因此,单个 RouteValueDictionary 参数。(见底部我的路线库评论)
Here I remove any routevalues from the request prior to generating a url.
在这里,我在生成 url 之前从请求中删除了任何路由值。
(note: for the array.contains ignorecase part, see: How can I make Array.Contains case-insensitive on a string array?)
(注意:对于 array.contains ignorecase 部分,请参阅:如何在字符串数组上使 Array.Contains 不区分大小写?)
public static string Action(this UrlHelper helper,
RouteValueDictionary routeValues)
{
RemoveRoutes(helper.RequestContext.RouteData.Values);
string url = helper.Action(routeValues["Action"].ToString(), routeValues);
return url;
}
public static void RemoveRoutes(RouteValueDictionary currentRouteData)
{
List<string> keyList = new List<string>(currentRouteData.Keys);
string[] ignore = new[] { "Area", "Controller", "Action" };
foreach (string key in keyList)
{
if (!ignore.Contains(key, StringComparer.CurrentCultureIgnoreCase))
currentRouteData.Remove(key);
}
}
I have Form and ActionLink extension methods that uses the RemoveRoutes method. No helper in my mvc library uses a method that is not an extension method i have created. Thereby, all routedata is cleaned up before generating urls.
我有使用 RemoveRoutes 方法的 Form 和 ActionLink 扩展方法。我的 mvc 库中没有任何助手使用不是我创建的扩展方法的方法。因此,在生成 url 之前清除所有路由数据。
For reference I use AttributeRouting. Here is an example of one route from my route library.
作为参考,我使用 AttributeRouting。这是我的路线库中的一条路线的示例。
public static RouteValueDictionary DisplayNews(int newsId)
{
RouteValueDictionary route = new RouteValueDictionary();
route["Area"] = _area;
route["Controller"] = _controller;
route["Action"] = "DisplayNews";
route["newsId"] = newsId;
return route;
}
回答by tmorell
So when I read objectbox's answer I thought I would have to modify several links in my code. I then tried adding a default route omitting the default parameters which solved the problem:
因此,当我阅读 objectbox 的答案时,我想我必须修改代码中的几个链接。然后我尝试添加一个默认路由,省略解决问题的默认参数:
routes.MapRoute(
"ArtistArtworkDefPage",
"Artist/{username}/Artwork",
new
{
controller = "Artist",
action = "Artwork",
page = 1
}
);
routes.MapRoute(
"ArtistArtwork",
"Artist/{username}/Artwork/{page}",
new
{
controller = "Artist",
action = "Artwork",
page = 1
},
new { page = @"\d+" }
);
回答by broadband
Simple example:
简单的例子:
public class ProductController : Controller
{
public ActionResult Edit(int id)
{
return View();
}
[Route("Product/Detail/{id:int}")]
public ActionResult Detail(int id)
{
return View();
}
}
Edit view contains only this:
编辑视图仅包含以下内容:
@{ Layout = null;}
@Url.Action("Detail", "Cmr")
So when you run your site e.g. localhost:randomPort/Product/Edit/123you get next response: /Product/Detail/123
因此,当您运行您的网站时,例如localhost:randomPort/Product/Edit/123您会得到下一个响应:/Product/Detail/123
Why? Because Routeattribute has required parameter id. Id parameter is read from url, although we wrote only Url.Action(methodName, controller)- without specifying parameter. Also it doesn't make sense to have a method detail without id.
为什么?因为Route属性有必需的参数id。id 参数是从 url 读取的,虽然我们只写了Url.Action(methodName, controller)- 没有指定参数。同样,没有 id 的方法细节也没有意义。
In order for attributes to work next line must be added to RouteConfig.cs:
为了使属性工作,必须将下一行添加到RouteConfig.cs:
public static void RegisterRoutes(RouteCollection routes)
{
...
routes.MapMvcAttributeRoutes();
...
}
回答by Ber'Zophus
Here's a workaround that doesn't require attribute routing, nor does it alter the current route values within your request. This idea comes from http://notherdev.blogspot.ca/2013/10/aspnet-mvc-current-values-used-by-url-action.html, which I altered slightly to work without MvcFutures.
这是一种不需要属性路由的解决方法,也不会更改请求中的当前路由值。这个想法来自http://notherdev.blogspot.ca/2013/10/aspnet-mvc-current-values-used-by-url-action.html,我稍微修改了它以在没有 MvcFutures 的情况下工作。
I built my own Actionextension on UrlHelper with an additional bool that allows you to optionally ignore the current route values (as to not clash with the existing Action methods on UrlHelper.)
我Action在 UrlHelper 上构建了自己的扩展,并带有一个额外的 bool,允许您选择性地忽略当前路由值(以免与 UrlHelper 上的现有 Action 方法发生冲突。)
What it does is builds a completely new RequestContext from the current one, by using the current route but notthe current route values. Then we pass that along to the base helpers. That way, when the base helpers go to look at what the route values are from within the request context, it'll find none, and thus not use them when generating the URL.
它所做的是通过使用当前路由而不是当前路由值从当前的 RequestContext 构建一个全新的 RequestContext 。然后我们将其传递给基础助手。这样,当基本帮助程序查看请求上下文中的路由值时,它将找不到任何值,因此在生成 URL 时不会使用它们。
public static string Action(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues, bool ignoreCurrentRouteValues=false) {
var routeValueDictionary = new RouteValueDictionary(routeValues);
var requestContext = urlHelper.RequestContext;
if (ignoreCurrentRouteValues) {
var currentRouteData = requestContext.RouteData;
var newRouteData = new RouteData(currentRouteData.Route, currentRouteData.RouteHandler);
requestContext = new RequestContext(requestContext.HttpContext, newRouteData);
}
return UrlHelper.GenerateUrl(null, actionName, controllerName, routeValueDictionary,
urlHelper.RouteCollection, requestContext, includeImplicitMvcValues: false);
}
回答by Mahdi Fathalla
A silly workaround I found that works to handle the current page routing data, including changing the page parameter upon your preferences
我发现一个愚蠢的解决方法可以处理当前页面路由数据,包括根据您的偏好更改页面参数
@{
var current_route_1 = new RouteValueDictionary(Url.RequestContext.RouteData.Values);
var current_route_2 = new RouteValueDictionary(Url.RequestContext.RouteData.Values);
//If you want to customize the routing values
current_route_1["controller"] = "Controller1";
current_route_2["controller"] = "Controller2";
}
@Url.RouteUrl(current_route_1);
@Url.RouteUrl(current_route_2);
回答by Martin Staufcik
A simple workaround would be first to call
一个简单的解决方法是首先调用
Url.Action("dummy", new { ... })
and then rename dummy in the resulting string to the correct action name.
然后将结果字符串中的 dummy 重命名为正确的操作名称。

