Ответ 1
В итоге я решил использовать следующую команду в web.config, чтобы решить эту проблему, используя Mvc2 и .Net Framework 4.0
<httpRuntime maxUrlLength="1000" relaxedUrlToFileSystemMapping="true" />
У меня есть приложение, где мы взяли старую структуру 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-адрес прошел определенную длину.
Вот что мы выяснили:
IIS имеет максимальный предел длины пути, но указанная выше ошибка не такова.
Изучите dot iis dot net Как использовать фильтрацию запросов Раздел "Фильтр на основе ограничений по запросу"
Если путь был слишком длинным для IIS, он бы выбрал 404.14, а не 400.0.
Кроме того, длина пути (и запроса) IIS настраивается:
<requestLimits
maxAllowedContentLength="30000000"
maxUrl="260"
maxQueryString="25"
/>
После того, как выкалывают:
Форумы 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, делает это еще больше.
Как вы думаете?
В итоге я решил использовать следующую команду в web.config, чтобы решить эту проблему, используя Mvc2 и .Net Framework 4.0
<httpRuntime maxUrlLength="1000" relaxedUrlToFileSystemMapping="true" />
Чтобы решить эту проблему, сделайте следующее:
В корневой 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>
...
Служба 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
Подробнее о настройках http.sys: http://support.microsoft.com/kb/820129
Максимальное допустимое значение - 32766. Если указано большее значение, оно будет проигнорировано. (Кредит: Хуан Мендес)
Для внесения изменений в этот параметр вступает в силу перезагрузка ПК. (Кредит: Дэвид Реттенбахер, Хуан Мендес)
ОК, поэтому часть причины, по которой я опубликовал это, также была связана с тем, что мы нашли работу.
Я надеюсь, что это будет полезно кому-то в будущем: 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
. Причина этого в том, что мне нужен доступ к значению заголовка позже канал запроса.)
Надеюсь, это поможет!
Я думаю, вы пытаетесь использовать GET. Попробуйте изменить метод запроса на POST и поместите эти параметры строки запроса в тело запроса.
Длинный URL-адрес не помогает SEO, не так ли?
Вероятно, сейчас неважно... но это сработало для меня (поскольку я не использовал файлы aspx, и я бы рискнул предположить, что это сработает для MVC):
Похоже, что максимальная длина URL-адреса с жестким кодом была исправлена в .NET 4.0. В частности, теперь есть раздел web.config
с:
<httpRuntime maxRequestPathLength="260" maxQueryStringLength="2048" />
который позволяет расширить диапазон разрешенных URL-адресов.