Подтвердить что ты не робот

ASP.NET MVC, Url Routing: максимальная длина пути (URL)

Сценарий

У меня есть приложение, где мы взяли старую структуру URL строки запроса:

?x=1&y=2&z=3&a=4&b=5&c=6

и изменил его на структуру пути:

/x/1/y/2/z/3/a/4/b/5/c/6

Мы используем ASP.NET MVC и (естественно) маршрутизацию ASP.NET.

Проблема

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

Это нормально, пока мы не попали в следующий поезд:

Ошибка HTTP 400.0 - неверный запрос ASP.NET обнаружил недопустимые символы в URL.

IIS выбрасывает эту ошибку, когда наш URL-адрес прошел определенную длину.

Nitty Gritty

Вот что мы выяснили:

Это не проблема IIS

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

Изучите dot iis dot net Как использовать фильтрацию запросов Раздел "Фильтр на основе ограничений по запросу"

Если путь был слишком длинным для IIS, он бы выбрал 404.14, а не 400.0.

Кроме того, длина пути (и запроса) IIS настраивается:

<requestLimits


   maxAllowedContentLength="30000000"


   maxUrl="260"


   maxQueryString="25" 


              />

Это проблема ASP.NET

После того, как выкалывают:

Форумы IIS Тема: максимальная длина URL-адреса ASP.NET 2.0? http://forums.iis.net/t/1105360.aspx

выясняется, что это проблема ASP.NET(ну, на самом деле .NET).

В основе дела лежит то, что, насколько я могу судить, ASP.NET не может обрабатывать пути длиной более 260 символов.

Гвоздь в гробу в том, что это подтверждается самим Филом Хааком:

Переполнение стека Предел MAX_PATH URL-адреса ASP.NET ID вопроса 265251

Вопрос

Итак, что вопрос?

Вопрос в том, насколько велика это ограничение?

Для моего приложения это убийца сделки. Для большинства приложений это, вероятно, не проблема.

Как насчет раскрытия? Нет, где упоминается ASP.NET Routing, я когда-либо слышал об этом ограничении. Тот факт, что ASP.NET MVC использует маршрутизацию ASP.NET, делает это еще больше.

Как вы думаете?

4b9b3361

Ответ 1

В итоге я решил использовать следующую команду в web.config, чтобы решить эту проблему, используя Mvc2 и .Net Framework 4.0

<httpRuntime maxUrlLength="1000" relaxedUrlToFileSystemMapping="true" />

Ответ 2

Чтобы решить эту проблему, сделайте следующее:

В корневой web.config для вашего проекта, в system.web node:

<system.web>
    <httpRuntime maxUrlLength="10999" maxQueryStringLength="2097151" />
...

Кроме того, мне пришлось добавить это в system.webServer node или я получил ошибку безопасности для моих длинных строк запроса:

<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxUrl="10999" maxQueryString="2097151" />
      </requestFiltering>
    </security>
...

Ответ 3

Служба Http.sys кодируется по умолчанию не более 260 символов на сегмент Url.

В этом контексте "сегмент URL" - это контент между символами "/" в Url. Например:

http://www.example.com/segment-one/segment-two/segment-three

Максимально допустимая длина сегмента Url может быть изменена с настройками реестра:

  • Ключ: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
  • Значение: UrlSegmentMaxLength
  • Тип: REG_DWORD
  • Данные: (Желаемая максимальная допустимая длина сегмента Url, например 4096)

Подробнее о настройках http.sys: http://support.microsoft.com/kb/820129

Максимальное допустимое значение - 32766. Если указано большее значение, оно будет проигнорировано. (Кредит: Хуан Мендес)

Для внесения изменений в этот параметр вступает в силу перезагрузка ПК. (Кредит: Дэвид Реттенбахер, Хуан Мендес)

Ответ 4

ОК, поэтому часть причины, по которой я опубликовал это, также была связана с тем, что мы нашли работу.

Я надеюсь, что это будет полезно кому-то в будущем: D

Обходной путь

Обходной путь довольно прост, и он тоже очень приятный.

Поскольку мы знаем, какие части сайта должны будут использовать динамические параметры (и, следовательно, будут иметь динамический путь и длину), мы можем избежать отправки этого длинного URL-адреса в маршрутизацию ASP.NET, перехватив его, прежде чем он даже попадет в ASP. NET

Введите IIS7 Url Rewriting (или любой эквивалентный модуль перезаписи).

Мы установили такое правило:

    <rewrite>
        <rules>
            <rule>
                <rule name="Remove Category Request Parameters From Url">
                <match url="^category/(\d+)/{0,1}(.*)$" />
                <action type="Rewrite" url="category/{R:1}" />
            </rule>
        </rules>
    </rewrite>

В основном, то, что мы делаем, просто удерживает достаточно пути, чтобы иметь возможность вызывать правильный маршрут вниз по течению. Остальная часть URL-адреса, которую мы взламываем.

Где находится оставшийся URL-адрес?

Ну, когда правило rewrite запущено, модуль Rewrite URL-адреса IIS7 автоматически устанавливает этот заголовок в запросе:

HTTP_X_ORIGINAL_URL

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

HttpContext.Request.Url.PathAndQuery

вместо этого мы смотрим на этот заголовок:

HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]

Проблема решена... почти!

Снег

Доступ к заголовку

Если вам нужно знать, чтобы получить доступ к заголовку модуля перезаписи IIS7, вы можете сделать это двумя способами:

HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]

или

HttpContext.Request.Headers["X-ORIGINAL-URL"]

Фиксирование относительных путей

Что вы также заметите, так это то, что с указанной выше настройкой все относительные пути прерываются (URL-адреса, которые были определены с помощью "~" ).

Это включает URL-адреса, определенные с помощью методов ASP.NET MVC HtmlHelper и UrlHelper (например, Url.Route("Bla")).

Здесь доступен доступ к коду ASP.NET MVC.

В методе System.Web.Mvc.PathHelper.GenerateClientUrlInternal() выполняется проверка того, существует ли один и тот же заголовок модуля Rewrite (см. выше):

// we only want to manipulate the path if URL rewriting is active, else we risk breaking the generated URL
NameValueCollection serverVars = httpContext.Request.ServerVariables;
bool urlRewriterIsEnabled = (serverVars != null && serverVars[_urlRewriterServerVar] != null);
if (!urlRewriterIsEnabled) {
    return contentPath;
}

Если это так, выполняется некоторая работа, чтобы сохранить исходный URL.

В нашем случае, поскольку мы не используем переписывание URL в "обычном" способе, мы хотим коротко закоротить этот процесс.

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

Самый простой взлом, который я мог придумать, заключался в том, чтобы полностью удалить эту переменную сервера, поэтому ASP.NET MVC не нашел бы ее:

protected void Application_BeginRequest()
{
    string iis7UrlRewriteServerVariable = "HTTP_X_ORIGINAL_URL";

    string headerValue = Request.ServerVariables[iis7UrlRewriteServerVariable];

    if (String.IsNullOrEmpty(headerValue) == false)
    {
        Request.ServerVariables.Remove(iis7UrlRewriteServerVariable);

        Context.Items.Add(iis7UrlRewriteServerVariable, headerValue);
    }
}

(Обратите внимание, что в вышеприведенном методе я удаляю заголовок из Request.ServerVariables, но сохраняю его, помещая его в Context.Items. Причина этого в том, что мне нужен доступ к значению заголовка позже канал запроса.)

Надеюсь, это поможет!

Ответ 5

Я думаю, вы пытаетесь использовать GET. Попробуйте изменить метод запроса на POST и поместите эти параметры строки запроса в тело запроса.

Длинный URL-адрес не помогает SEO, не так ли?

Ответ 7

Похоже, что максимальная длина URL-адреса с жестким кодом была исправлена ​​в .NET 4.0. В частности, теперь есть раздел web.config с:

<httpRuntime maxRequestPathLength="260" maxQueryStringLength="2048" /> 

который позволяет расширить диапазон разрешенных URL-адресов.