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 маршрутизация.

Проблема

проблема в том, что наши параметры динамичны, и (теоретически) нет предела количеству параметров, которые нам нужно учитывать.

все в порядке пока нас не сбил следующий поезд:--6-->

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

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

Nitty Gritty

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

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

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

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

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

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

<requestLimits


   maxAllowedContentLength="30000000"


   maxUrl="260"


   maxQueryString="25" 


              />

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

после некоторого ковыряния вокруг:

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

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

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

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

Вопрос

так в чем вопрос?

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

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

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

что вы думаете?

7 ответов


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

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

чтобы решить эту проблему, делаем так:

в корневой сети.config для вашего проекта, под системой.веб-узел:

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

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

<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 может быть изменена с помощью параметров реестра:


    Итак, отчасти поэтому я написал это потому, что мы обойти.

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

    решение

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

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

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

    мы установили правило, как это:

        <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-адреса?

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

    HTTP_X_ORIGINAL_URL
    

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

    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() способ, есть делаются проверьте если существует тот же заголовок модуля перезаписи URL (см. выше):

    // 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, не так ли?


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

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

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


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

    Ошибка 404

    исправление для меня было описано выше путем обновления веб.config с обоими из следующих тегов:

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

    и

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