ASP.NET MVC, Routing Url: Lunghezza massima percorso (URL)

Lo scenario

Ho un’applicazione in cui abbiamo preso la buona vecchia struttura URL della stringa di query:

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

e cambiato in una struttura di percorso:

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

Stiamo usando ASP.NET MVC e (naturalmente) il routing di ASP.NET.

Il problema

Il problema è che i nostri parametri sono dinamici e non esiste (teoricamente) alcun limite alla quantità di parametri per cui dobbiamo adattarci.

Questo va bene fino a quando non siamo stati colpiti dal treno seguente:

Errore HTTP 400.0 – Richiesta non valida ASP.NET ha rilevato caratteri non validi nell’URL.

IIS genererebbe questo errore quando il nostro URL ha superato una certa lunghezza.

The Nitty Gritty

Ecco cosa abbiamo scoperto:

Questo non è un problema con IIS

IIS ha un limite di lunghezza del percorso massimo, ma l’errore precedente non è questo.

Apprendi dot iis dot net Come utilizzare la sezione di filtraggio delle richieste “Filtro basato sui limiti della richiesta”

Se il percorso era troppo lungo per IIS, genererebbe un 404.14, non un 400.0.

Inoltre, la lunghezza massima del percorso (e della query) di IIS è configurabile:

  

Questo è un problema ASP.NET

Dopo un po ‘di curiosità:

Thread forum IIS: lunghezza massima dell’URL di ASP.NET 2.0? http://forums.iis.net/t/1105360.aspx

si scopre che questo è un problema ASP.NET (beh, .NET davvero).

Il nocciolo della questione è che, per quanto posso dire, ASP.NET non può gestire percorsi più lunghi di 260 caratteri.

L’unghia nella bara è confermata dallo stesso Phil lo Haack:

Limite di stack URL ASP.NET limite MAX_PATH ID domanda 265251

La domanda

Quindi qual è la domanda?

La domanda è: quanto è grande questa limitazione?

Per la mia app, è un killer affare. Per la maggior parte delle app, probabilmente è un non-problema.

Che dire della divulgazione? No, dove è menzionato il routing ASP.NET, ho mai sentito parlare di questa limitazione. Il fatto che ASP.NET MVC utilizzi il routing ASP.NET rende l’impatto ancora più grande.

Cosa ne pensi?

Ho finito per usare il seguente nel web.config per risolvere questo problema usando Mvc2 e .Net Framework 4.0

  

Per risolvere questo, fai questo:

Nel root web.config per il tuo progetto, sotto il nodo system.web:

   ... 

Inoltre, ho dovuto aggiungere questo sotto il nodo system.webServer o ho ricevuto un errore di sicurezza per le mie lunghe stringhe di query:

       ... 

Il servizio Http.sys è codificato con un massimo predefinito di 260 caratteri per segmento di URL.

Un “segmento di URL” in questo contesto è il contenuto tra i caratteri “/” nell’URL. Per esempio:

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

La lunghezza massima consentita per il segmento Url può essere modificata con le impostazioni del Registro di sistema:

  • Chiave: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
  • Valore: UrlSegmentMaxLength
  • Digitare: REG_DWORD
  • Dati: (la lunghezza massima consentita per il nuovo segmento Url, ad es. 4096)

Ulteriori informazioni sulle impostazioni http.sys: http://support.microsoft.com/kb/820129

Il valore massimo consentito è 32766. Se viene specificato un valore maggiore, verrà ignorato. (Credito: Juan Mendes)

È necessario riavviare il PC per rendere effettive le modifiche a questa impostazione. (Credito: David Rettenbacher, Juan Mendes)

OK, quindi parte del motivo per cui ho postato questo è stato anche perché abbiamo trovato un lavoro in giro.

Spero che questo possa essere utile a qualcuno in futuro: D

La soluzione

La soluzione è abbastanza semplice, ed è anche abbastanza bella.

Poiché sappiamo quali parti del sito dovranno utilizzare i parametri dinamici (e quindi avranno un percorso e una lunghezza dinamici), possiamo evitare di inviare questo lungo url al routing di ASP.NET intercettandolo prima che colpisca anche ASP.NET

Immettere IIS7 Url Rewriting (o qualsiasi modulo di riscrittura equivalente).

Abbiamo impostato una regola come questa:

           

Fondamentalmente, quello che stiamo facendo è mantenere abbastanza del percorso per poter chiamare il percorso corretto a valle. Il resto del percorso dell’URL che stiamo hackerando.

Dove va il resto dell’URL?

Bene, quando viene triggersta una regola di riscrittura, il modulo Riscritto URL IIS7 imposta automaticamente questa intestazione nella richiesta:

 HTTP_X_ORIGINAL_URL 

A valle, nella parte dell’app che analizza il percorso dinamico, invece di guardare il percorso:

 HttpContext.Request.Url.PathAndQuery 

guardiamo invece quell’intestazione:

 HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"] 

Problema risolto … quasi!

Gli ostacoli

Accesso all’intestazione

Nel caso in cui sia necessario sapere, per accedere all’intestazione del modulo Rewrite di IIS7, è ansible farlo in due modi:

 HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"] 

o

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

Correggere i percorsi relativi

Quello che noterete anche è che, con l’impostazione di cui sopra, tutti i percorsi relativi si interrompono (URL che sono stati definiti con un “~”).

Ciò include gli URL definiti con i metodi ASP.NET MVC HtmlHelper e UrlHelper (come Url.Route("Bla") ).

Qui è dove l’accesso al codice MVC ASP.NET è fantastico.

Nel metodo System.Web.Mvc.PathHelper.GenerateClientUrlInternal() , viene eseguito un controllo per verificare se esiste la stessa intestazione URL Rewrite module (vedere sopra):

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

Se lo fa, si fa del lavoro per preservare l’URL di origine.

Nel nostro caso, dal momento che non stiamo usando la riscrittura degli URL in modo “normale”, vogliamo cortocircuitare questo processo.

Vogliamo fingere che non si sia verificata la riscrittura degli URL, poiché non vogliamo che i percorsi relativi vengano considerati nel contesto dell’URL originale.

Il trucco più semplice a cui potevo pensare era quello di rimuovere completamente quella variabile del server, quindi ASP.NET MVC non lo trovava:

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

(Si noti che, nel metodo precedente, sto rimuovendo l’intestazione da Request.ServerVariables ma continuando a conservarlo, nascondendolo in Context.Items . Il motivo è che ho bisogno di accedere al valore dell’intestazione più avanti nella pipe di richiesta .)

Spero che questo ti aiuti!

Penso che tu stia cercando di usare GET. Prova a cambiare il metodo di richiesta su POST e inserisci questi parametri di stringa di query nel corpo della richiesta.

Anche l’URL lungo non aiuta il SEO, vero?

Sembra che la lunghezza massima dell’URL hardcoded sia stata risolta in .NET 4.0 . In particolare, ora c’è una sezione web.config con:

  

che ti consente di espandere l’intervallo di URL consentiti.

Stavo riscontrando un problema di lunghezza dell’URL massimo simile utilizzando l’API Web ASP.NET 4, che generava un errore leggermente diverso:

404 Errore

La correzione per me è stata descritta sopra aggiornando Web.config con ENTRAMBI i seguenti tag:

   

e