2009-02-05 2 views
7

Я заметил, что URL-адрес возвращаемого URL-адреса в ссылках на вход/выход в Stackoverflow не экранирован, но когда я пытаюсь добавить путь в качестве параметра к маршруту, который он экранирует.Как оставить параметры URL, не привязанные в ASP.NET MVC?

So/login? Returnurl =/questions/ask показывает/login? Returnurl =% 2fquestions% 2fask и это отвратительно. Как мне заставить его не уклоняться от значения returnurl?

Вот что я делаю в коде:

Html.ActionLink("Login", "Login", "Account", new { returnurl=Request.Path }, null) 
+0

Хотелось бы узнать ответ на этот вопрос –

ответ

1

Я понимаю один из комментариев о кодировании, происходящем по причине; это будет только исключение, а не правило.

Вот что я собрал, как его можно улучшить?

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); 
    } 
+0

Работает немного лучше, если у вас есть он, возвращающий MvcHtmlString. –

0

Моя solutionto аналогичная проблема была, чтобы написать свое собственное расширение. После копания в коде я не мог найти способ сделать это иначе. Ваш может выглядеть так.

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(); 
    } 
} 

Я думаю, что у меня была такая же проблема изготовления и использования UrlHelper поэтому я пошел с механизмом string.Format вместо этого. YMMV.

+0

Единственная проблема заключается в том, что вы жестко программируете маршрут, а это означает, что это сломается, если вы не используете маршрут по умолчанию. – JMS

+0

Это был всего лишь пример с моей головы. Вероятно, вы могли бы использовать UrlHelper для построения маршрута из action/controller, а затем добавить параметры запроса до конца. – tvanfosson

6

Как заставить его не избежать значение ReturnUrl

Как про это?

var url = Url.Action("Login", "Account", new {returnurl = Request.Path}); 
var unEncodedUrl = HttpUtility.UrlDecode(url); 
Response.Write("<a href='" + unEncodedUrl + "'>...</a>"); 

Будьте уверены, что это то, что вы хотите, хотя, URL encoding has its purpose.

+1

Быстрое решение. Может потребоваться использовать @ Html.Raw (unEncodedUrl), если вы создаете какой-либо контент JS. –

0

Я не верю, что есть способ вокруг него, которая встроена в рамки. Фактическое построение URL-адреса происходит в методе System.Web.Routing.ParsedRoute.Bind, и нет никаких условий, используемых для предотвращения экранирования.

Похоже, что метод расширения - это путь, который немного более прочный, чем тот, который упоминался ранее.

1

Параметр не неэкранированный. Вы увидите URL-адрес:

http://stackoverflow.com/users/login?returnurl=%2fquestions%2fask 

действительно работает - SO считывает и отменяет этот параметр как обычно. Если вы хотите включить другие параметры вне границ, такие как '&' в параметр, вам все равно придется их избегать.

Хитрость заключается лишь в том, что символ «/», в частности, не должен быть%-экранирован в параметрах запроса. Это делает должен быть экранирован в других контекстах, например, в части пути, поэтому URLEncode всегда кодирует его, чтобы быть в безопасности.

Если вы хотите, чтобы URL-адрес выглядел красивее, просто избегайте параметра как обычно (что вы должны сделать, чтобы избежать всех других символов, которые должны быть обработаны правильно), а затем замените строку на «% 2f» на '/'.

+0

Я знаю, что URL будет работать, но мне не нравится внешний вид, видимо, Джефф и команда в SO чувствовали то же самое. Это решение слишком много для взлома. – Todd

+0

Гарантируется, что он останется действительным URL-адресом, если только параметры unescape% 2F. Ваш код выше упадет на любой другой символ, который недействителен в параметрах, например. &, ; или%. – bobince

+0

Как я уже сказал, это исключение, а не правило. – Todd

 Смежные вопросы

  • Нет связанных вопросов^_^