2012-02-01 27 views
14

Normalmente non mi mettere un titolo come questo nella questione, ma io sono abbastanza sicuro che si tratta di un bug (o di proposito?)Possibile errore con il routing di ASP.NET MVC 3?

Ho creato un nuovo ASP.NET MVC 3 Web Application.

Quindi sono andato alla pagina/Home/Info.

L'URL per questa pagina è:

http://localhost:51419/Home/About

Poi ho cambiato l'URL a questo:

http://localhost:51419/(A(a))/Home/About

E pagina ha funzionato? Osservando i valori del percorso, controller = Home, Azione = Informazioni. È ignorata la prima parte?

E se guardo tutti gli anelli della fonte:

<link href="/(A(a))/Content/Site.css" rel="stylesheet" type="text/css" /> 
<script src="/(A(a))/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script> 
<script src="/(A(a))/Scripts/modernizr-1.7.min.js" type="text/javascript"></script> 

<li><a href="/(A(a))/">Home</a></li> 
<li><a href="/(A(a))/Home/About">About</a></li> 

vedere come si sosteneva che prima parte? È come se il motore di routing pensasse che fosse parte del dominio o qualcosa del genere?

ho una sensazione è un'espressione regolare cosa , perché se cambio l'URL:

http://localhost:51419/(a(a))/Home/About

(per esempio ha cambiato la A maiuscola in minuscolo)

E 404 di.

Qualcuno può far luce su questo? È un bug o di progettazione?

+2

È una cosa rara che un post con "possibile bug" nel titolo sia votato, IMO. Questo è. –

+1

@AndrewBarber - lo so. :) È un colpo di fortuna, mi sono imbattuto in questo. Google stava indicizzando alcuni URL strani con guid in loro, causati da un bug nella nostra applicazione. – RPM1984

risposta

5

Questo sembra essere correlato a sessioni senza figli nella pipeline ASP.NET. Si spoglia quel modello URL all'interno CookielessHelper.cs (System.Web.Security) durante l'elaborazione della richiesta:

// This function is called for all requests -- it must be performant. 
    // In the common case (i.e. value not present in the URI, it must not 
    // look at the headers collection 
    internal void RemoveCookielessValuesFromPath() 
    { 
     // See if the path contains "/(XXXXX)/" 
     string path  = _Context.Request.ClientFilePath.VirtualPathString; 
     // Optimize for the common case where there is no cookie 
     if (path.IndexOf('(') == -1) { 
      return; 
     } 
     int  endPos = path.LastIndexOf(")/", StringComparison.Ordinal); 
     int  startPos = (endPos > 2 ? path.LastIndexOf("/(", endPos - 1, endPos, StringComparison.Ordinal) : -1); 

     if (startPos < 0) // pattern not found: common case, exit immediately 
      return; 

     if (_Headers == null) // Header should always be processed first 
      GetCookielessValuesFromHeader(); 

     // if the path contains a cookie, remove it 
     if (IsValidHeader(path, startPos + 2, endPos)) 
     { 
      // only set _Headers if not already set 
      if (_Headers == null) { 
       _Headers = path.Substring(startPos + 2, endPos - startPos - 2); 
      } 
      // Rewrite the path 
      path = path.Substring(0, startPos) + path.Substring(endPos+1); 

      // remove cookie from ClientFilePath 
      _Context.Request.ClientFilePath = VirtualPath.CreateAbsolute(path); 
      // get and append query string to path if it exists 
      string rawUrl = _Context.Request.RawUrl; 
      int qsIndex = rawUrl.IndexOf('?'); 
      if (qsIndex > -1) { 
       path = path + rawUrl.Substring(qsIndex); 
      } 
      // remove cookie from RawUrl 
      _Context.Request.RawUrl = path; 

      if (!String.IsNullOrEmpty(_Headers)) { 
       _Context.Request.ValidateCookielessHeaderIfRequiredByConfig(_Headers); // ensure that the path doesn't contain invalid chars 
       _Context.Response.SetAppPathModifier("(" + _Headers + ")"); 

       // For Cassini and scenarios where aspnet_filter.dll is not used, 
       // HttpRequest.FilePath also needs to have the cookie removed. 
       string filePath = _Context.Request.FilePath; 
       string newFilePath = _Context.Response.RemoveAppPathModifier(filePath); 
       if (!Object.ReferenceEquals(filePath, newFilePath)) { 
        _Context.RewritePath(VirtualPath.CreateAbsolute(newFilePath), 
             _Context.Request.PathInfoObject, 
             null /*newQueryString*/, 
             false /*setClientFilePath*/); 
       } 
      } 
     } 
    } 

vostro modello corrisponde a questo:

/////////////////////////////////////////////////////////////////////// 
    /////////////////////////////////////////////////////////////////////// 
    // Make sure sub-string if of the pattern: A(XXXX)N(XXXXX)P(XXXXX) and so on. 
    static private bool IsValidHeader(string path, int startPos, int endPos) 
    { 
     if (endPos - startPos < 3) // Minimum len is "X()" 
      return false; 

     while (startPos <= endPos - 3) { // Each iteration deals with one "A(XXXX)" pattern 

      if (path[startPos] < 'A' || path[startPos] > 'Z') // Make sure pattern starts with a capital letter 
       return false; 

      if (path[startPos + 1] != '(') // Make sure next char is '(' 
       return false; 

      startPos += 2; 
      bool found = false; 
      for (; startPos < endPos; startPos++) { // Find the ending ')' 

       if (path[startPos] == ')') { // found it! 
        startPos++; // Set position for the next pattern 
        found = true; 
        break; // Break out of this for-loop. 
       } 

       if (path[startPos] == '/') { // Can't contain path separaters 
        return false; 
       } 
      } 
      if (!found) { 
       return false; // Ending ')' not found! 
      } 
     } 

     if (startPos < endPos) // All chars consumed? 
      return false; 

     return true; 
    } 
+0

Hmm, sooo ... è un errore allora? Non sono sicuro se si tratta di una cosa principale ASP.NET, in quanto tale codice ha senso. MA, il motore di routing ASP.NET (beh, almeno il routing MVC), IMO non dovrebbe accettarlo come parte del percorso (ad esempio, non dovrebbe corrispondere). Dovrei aumentare questo con MS? – RPM1984

+0

@ RPM1984 No, è chiaramente "in base alla progettazione" il modo in cui tracciano l'utente che ha effettuato l'accesso quando i cookie non sono disponibili. Fai finta di non averlo mai notato e tutto andrà bene. –

+0

@RobertLevy: non posso ignorarlo. Questo mi sta effettivamente accadendo con un'applicazione live. Come ho detto nel commento, Google sta indicizzando alcuni URL strani che corrispondono a questo modello. Quindi, poiché MVC li sta accettando come percorsi validi, stanno semplicemente raggiungendo i miei controller e poi morendo in seguito. Quando davvero dovrebbero essere 404'ed fin dall'inizio. Anche gli URL sono casuali, quindi non posso facilmente mettere una riscrittura sul posto. È abbastanza giusto che questo sia "di progettazione" per ASP.NET, ma penso che questo sia un bug in MVC. NON dovrebbe accettarlo come una rotta. – RPM1984

-1

Sono d'accordo con l'analisi @pjumble, ma non per la sua soluzione.
Disabilitare l'autenticazione senza cookie per l'autenticazione del modulo o l'autenticazione anonima.

Ciò impedirà agli utenti con cookie disabilitati di autenticarsi. Ma a chi importa, tutti oggi hanno i cookie attivati ​​perché nessun sito web moderno funzionerà senza.

Aggiungere nel web.config:

<anonymousIdentification enabled="false" /> 
<authentication mode="None" /> 

o

<anonymousIdentification enabled="true" cookieless="UseCookies" ... /> 
<authentication mode="Forms"> 
    <forms name="Auth" cookieless="UseCookies" ... /> 
</authentication> 
+0

BTW, qual era la "soluzione" di @ pjumble, non la vedo, solo una diagnosi. – RPM1984

+0

si bloccherebbe qualche gruppo di utenti dall'accesso solo a causa di una strana stranezza nell'analisi dell'URL di .net? –

+0

"Ma chi se ne importa comunque" la maggior parte del reparto vendite per un inizio ... – Basic

0

si potrebbe desiderare di provare ad aggiungere un IgnoreRoute per la mappatura percorso - ma ammettere che non sono sicuro di quale formato per fornire per abbinare tutti i tuoi possibili percorsi senza cuoco.

Problemi correlati