70 votes

ASP.NET MVC, Acheminement des URL : Longueur maximale du chemin (URL)

Le scénario

J'ai une application où nous avons utilisé la bonne vieille structure URL à chaîne de requête :

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

et l'a transformé en une structure de chemin :

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

Nous utilisons ASP.NET MVC et (naturellement) ASP.NET routing.

Le problème

Le problème est que nos paramètres sont dynamiques et qu'il n'y a (théoriquement) aucune limite au nombre de paramètres à prendre en compte.

Tout va bien jusqu'à ce que nous soyons percutés par le train suivant :

Erreur HTTP 400.0 - Mauvaise requête ASP.NET a détecté des caractères invalides dans l'URL.

IIS lançait cette erreur quand l'URL dépassait une certaine longueur.

L'essentiel

Voici ce que nous avons découvert :

Ce n'est pas un problème IIS

IIS a bien une limite de longueur maximale des chemins, mais l'erreur ci-dessus n'en fait pas partie.

Apprendre dot iis dot net Comment utiliser le filtrage des requêtes Section "Filtrer en fonction des limites de demande

Si le chemin était trop long pour IIS, il renverrait un 404.14, et non un 400.0.

En outre, la longueur maximale des chemins (et des requêtes) d'IIS est configurable :

<requestLimits

   maxAllowedContentLength="30000000"

   maxUrl="260"

   maxQueryString="25" 

              />

C'est un problème d'ASP.NET

Après avoir fouillé un peu :

Forums IIS Sujet : ASP.NET 2.0 longueur maximale des URL ? http://forums.iis.net/t/1105360.aspx

il s'avère qu'il s'agit d'un problème ASP.NET (enfin, .NET en fait).

Le cœur du problème est que, pour autant que je sache, ASP.NET ne peut pas gérer les chemins d'accès de plus de 260 caractères.

Le clou du cercueil est que cela est confirmé par Phil le Haack lui-même :

Stack Overflow ASP.NET url limite MAX_PATH Question ID 265251

La question

Alors quelle est la question ?

La question est de savoir à quel point cette limitation est importante.

Pour mon application, c'est une fatalité. Pour la plupart des applications, ce n'est probablement pas un problème.

Qu'en est-il de la divulgation ? À aucun endroit où ASP.NET Routing est mentionné, je n'ai entendu parler de cette limitation. Le fait que ASP.NET MVC utilise ASP.NET Routing rend l'impact de cette limitation encore plus grand.

Qu'en pensez-vous ?

46voto

lmingle Points 506

J'ai fini par utiliser les éléments suivants dans le web.config pour résoudre ce problème en utilisant Mvc2 et .Net Framework 4.0

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

0 votes

La longueur maximale de l'URL peut être de 2097151.

1 votes

Nogo pour la limite de 260 segments, également modifié support.microsoft.com/fr/us/kb/820129 UrlSegmentMaxCount également nogo

0 votes

Oui, le relaxedUrlToFileSystemMapping est la seule solution.

33voto

theJerm Points 1521

Pour résoudre ce problème, faites ceci :

Dans le web.config racine de votre projet, sous le nœud system.web :

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

En outre, j'ai dû l'ajouter sous le nœud system.webServer, sinon j'ai obtenu une erreur de sécurité pour mes longues chaînes de requête :

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

0 votes

Ça a marché pour moi, le noeud system.webServer est important !

1 votes

@edelwater il semble qu'il s'agisse d'une vérification des règles du système de fichiers, mais le fait de mettre relaxedUrlToFileSystemMapping à true n'aide pas non plus.

0 votes

J'ai résolu mon problème dans l'application rest api pour gérer les requêtes GET très longues.

33voto

David Richoz Points 71

Le service Http.sys est codé avec un maximum par défaut de 260 caractères par segment Url.

Dans ce contexte, un "segment d'URL" est le contenu entre les caractères "/" de l'URL. Par exemple :

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

La longueur maximale autorisée des segments d'URL peut être modifiée à l'aide des paramètres du registre :

  • Clé : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
  • Valeur : UrlSegmentMaxLength
  • Type : REG_DWORD
  • Données : (La longueur maximale autorisée de votre nouveau segment Url, par exemple 4096)

En savoir plus sur les paramètres de http.sys : http://support.microsoft.com/kb/820129

La valeur maximale autorisée est de 32766. Si une valeur supérieure est spécifiée, elle sera ignorée. (Crédit : Juan Mendes)

Le redémarrage du PC est nécessaire pour qu'une modification de ce paramètre prenne effet. (Crédit : David Rettenbacher, Juan Mendes)

0 votes

Cela a réglé le problème pour moi aussi. Nous avions un segment d'url vraiment long (note : pas la longueur totale de l'url) qui causait le problème. Je suppose que dans ce cas, il faut se demander si vous faites bien les choses quand un seul segment d'url fait plus de 260 caractères !

1 votes

Il convient de noter qu'un un redémarrage est nécessaire pour que ce paramètre prenne effet.

3 votes

Redémarrage de la machine ou seulement IIS ?

17voto

Martin Su Points 1163

OK, si j'ai posté ce message, c'est aussi parce que nous avons trouvé une solution.

J'espère que cela sera utile à quelqu'un dans le futur :D

La solution de contournement

La solution de contournement est très simple, et elle est aussi très agréable.

Comme nous savons quelles parties du site devront utiliser des paramètres dynamiques (et auront donc un chemin et une longueur dynamiques), nous pouvons éviter d'envoyer cette longue url au routage ASP.NET en l'interceptant avant même qu'elle n'atteigne ASP.NET.

Entrez dans IIS7 Url Rewriting (ou tout autre module de réécriture équivalent).

Nous avons mis en place une règle comme celle-ci :

    <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>

En fait, ce que nous faisons, c'est que nous gardons juste assez du chemin pour être capable d'appeler la bonne route en aval. Le reste du chemin de l'URL, nous le coupons.

Où va le reste de l'URL ?

Lorsqu'une règle de réécriture est activée, le module IIS7 URL Rewrite place automatiquement cet en-tête dans la requête :

HTTP_X_ORIGINAL_URL

En aval, dans la partie de l'application qui analyse le chemin dynamique, au lieu de regarder le chemin :

HttpContext.Request.Url.PathAndQuery

nous regardons cet en-tête à la place :

HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]

Problème résolu... ou presque !

Les accrocs

Accès à l'en-tête

Si vous avez besoin de savoir comment accéder à l'en-tête du module de réécriture d'IIS7, vous pouvez le faire de deux manières :

HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]

ou

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

Correction des chemins relatifs

Vous remarquerez également qu'avec la configuration ci-dessus, tous les chemins relatifs sont rompus (les URL définies avec un "~").

Cela inclut les URLs définis avec l'option ASP.NET MVC HtmlHelper et UrlHelper (comme Url.Route("Bla") ).

C'est là que l'accès au code ASP.NET MVC est génial.

Dans le System.Web.Mvc.PathHelper.GenerateClientUrlInternal() une vérification est effectuée pour voir si le même en-tête de module URL Rewrite existe (voir ci-dessus) :

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

Si c'est le cas, un travail est effectué pour préserver l'URL d'origine.

Dans notre cas, comme nous n'utilisons pas la réécriture d'URL de manière "normale", nous voulons court-circuiter ce processus.

Nous voulons faire comme si aucune réécriture d'URL n'avait eu lieu, puisque nous ne voulons pas que les chemins relatifs soient considérés dans le contexte de l'URL d'origine.

La solution la plus simple à laquelle j'ai pensé était de supprimer complètement cette variable de serveur, afin que ASP.NET MVC ne la trouve pas :

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

(Notez que, dans la méthode ci-dessus, j'enlève l'en-tête de Request.ServerVariables mais en le conservant, en le mettant de côté dans Context.Items . La raison en est que j'ai besoin d'accéder à la valeur de l'en-tête plus tard dans le pipe de la requête).

J'espère que cela vous aidera !

0 votes

Pouvez-vous définir cette réponse ?

0 votes

J'ai défini cette réponse conformément à votre demande.

0 votes

Si je fais cela, dois-je également modifier le fichier web.config ? Je voudrais éviter de modifier le fichier web.config afin de pouvoir autoriser les longues requêtes vers une seule URL particulière, tout en les bloquant normalement pour toutes les autres.

2voto

Adrian Godong Points 5367

Je pense que vous essayez trop d'utiliser GET. Essayez de changer la méthode de requête en POST et mettez ces paramètres de chaîne de requête dans le corps de la requête.

Une URL longue n'aide pas non plus le référencement, n'est-ce pas ?

5 votes

J'utilise GET pour deux raisons : 1) Ces URL doivent être partagées et doivent être persistantes. 2) Je ne poste rien. Il s'agit d'une opération de lecture. > Une URL longue n'aide pas non plus le référencement, n'est-ce pas ? Je ne suis pas sûr, mais si la demande est complexe, la requête l'est aussi... il n'y a aucun moyen de contourner ce problème, à moins d'utiliser des URL non sémantiques à la place.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X