可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I've noticed the returnurl URL parameter on the Stackoverflow login/logout links are not escaped but when I try to add path as a parameter to a route it gets escaped.
So /login?returnurl=/questions/ask shows /login?returnurl=%2fquestions%2fask and it's kind of ugly. How do I get it to not escape the returnurl value?
Here's what I'm doing in the code:
Html.ActionLink("Login", "Login", "Account", new { returnurl=Request.Path }, null)
回答1:
How do I get it to not escape the
returnurl value
How's about this?
var url = Url.Action("Login", "Account", new {returnurl = Request.Path});
var unEncodedUrl = HttpUtility.UrlDecode(url);
Response.Write("<a href='" + unEncodedUrl + "'>...</a>");
Be sure that's what you want though, URL encoding has its purpose.
回答2:
I understand one of the comments about encoding happening for a reason; this would only be an exception, not the rule.
Here's what I put together, how can it be improved?
public static string ActionLinkNoEscape(this HtmlHelper html, string linkText, string actionName, string controllerName, object values, object htmlAttributes)
{
RouteValueDictionary routeValues = new RouteValueDictionary(values);
RouteValueDictionary htmlValues = new RouteValueDictionary(htmlAttributes);
UrlHelper urlHelper = new UrlHelper(html.ViewContext.RequestContext, RouteTable.Routes);
string url = urlHelper.Action(actionName, controllerName);
url += "?";
List<string> paramList = new List<string>();
foreach (KeyValuePair<string, object> pair in routeValues)
{
object value = pair.Value ?? "";
paramList.Add(String.Concat(pair.Key, "=", Convert.ToString(value, CultureInfo.InvariantCulture)));
}
url += String.Join("&", paramList.ToArray());
TagBuilder builder = new TagBuilder("a");
builder.InnerHtml = string.IsNullOrEmpty(linkText) ? "" : HttpUtility.HtmlEncode(linkText);
builder.MergeAttributes<string, object>(htmlValues);
builder.MergeAttribute("href", url);
return builder.ToString(TagRenderMode.Normal);
}
回答3:
The parameter is not unescaped. You'll notice the URL:
http://stackoverflow.com/users/login?returnurl=%2fquestions%2fask
does actually work - SO is reading and unescaping that parameter as normal. If you wanted to include other out-of-bounds characters such as '&' in the parameter you would still have to escape them.
The trick is merely that the '/' character in particular does not need to be %-escaped in query parameters. It does have to be escaped in other contexts such as in a path part, so URLEncode always encodes it, to be safe.
If you just want the URL to look prettier, simply escape the parameter as normal (which you must do to escape all the other characters that must be handled correctly), and then do a string replace on '%2f' with '/'.
回答4:
My solutionto a similar problem was to write my own extension. After digging around in the code I couldn't find a way to do it otherwise. Yours might look like this.
public static class HtmlHelperExtensions
{
public static string LoginLinkWithReturnUrl( this HtmlHelper helper,
string linkText,
string action,
string controller,
string returnUrl,
object htmlAttributes )
{
TagBuilder builder = new TagBuilder("a");
builder.Attributes.Add( "href",
string.Format( "/{0}/{1}?returnurl={2}",
controller,
action,
returnUrl ) );
var attrDict = new RouteValueDictionary( htmlAttributes );
builder.MergeAttributes( attrDict );
builder.InnerHtml = linkText;
return builder.ToString();
}
}
I think I had the same problem making and using a UrlHelper so I went with the string.Format mechanism instead. YMMV.
回答5:
I don't believe there's a way around it that's built into the framework. The actual construction of the URL happens in the System.Web.Routing.ParsedRoute.Bind method and there aren't any conditions used to prevent the escaping.
Looks like an extension method is the way to go but one that is slightly more robust than the one mentioned previously.