Как оставить параметры URL неэкранированными в ASP.NET MVC?

StackOverflow https://stackoverflow.com/questions/514440

  •  21-08-2019
  •  | 
  •  

Вопрос

Я заметил, что параметр URL returnurl в ссылках Stackoverflow login / logout не экранируется, но когда я пытаюсь добавить path в качестве параметра к маршруту, он экранируется.

Итак, /login?returnurl=/questions/ask показывает /login?returnurl=%2fquestions%2fask, и это как-то некрасиво.Как мне сделать так, чтобы значение returnurl не экранировалось?

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

Html.ActionLink("Login", "Login", "Account", new { returnurl=Request.Path }, null)
Это было полезно?

Решение 2

Я понимаю, что один из комментариев о кодировании происходит по какой-то причине;это было бы всего лишь исключением, а не правилом.

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

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

Другие советы

Как мне заставить его не экранировать значение returnurl

Как насчет этого?

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

Но будь уверен, что это то, чего ты хочешь, Кодировка URL-адресов имеет свое назначение.

Этот параметр равен нет незамеченный.Вы заметите URL-адрес:

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

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

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

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

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

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.Вместо этого механизм форматирования.ИММВ.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top