2013-02-27 9 views
17

IIS und ASP.NET (MVC) has some glitches beim Arbeiten mit URLs mit% -encoding im Pfad (nicht die Query-Zeichenfolge; die Abfrage-Zeichenfolge ist in Ordnung). Wie kann ich das umgehen? Wie kann ich die tatsächliche URL erhalten, die angefordert wurde?Wie kann ich die tatsächliche URL zuverlässig ermitteln, auch wenn prozentuale Teile im Pfad enthalten sind?

Zum Beispiel, wenn ich /x%3Fa%3Db und (separat) zu /x?a=b navigieren - beide berichten über die .Request.Url als /x?a=b - weil die codierten Daten im Pfad falsch gemeldet wird.

+0

Während der Gedanke geschätzt wird, ist StackOverflow * nicht * eine Schnipsel-Website oder ein Ort, um Dinge, die Sie herausfinden, d. Die Zeitstempel deiner Frage und Antwort zeigen, dass du hierher gekommen bist, um beide zu veröffentlichen. Bitte schreiben Sie nur Fragen, bei denen Sie wirklich Hilfe benötigen. Es gibt geeignetere Möglichkeiten, Informationen nur mit der Community zu teilen. –

+29

@Chris [Selbstbeantwortung war schon immer akzeptabel] (http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/). Die Entscheidung, die Antwort * als Teil des Fragens * zuzulassen, wurde ebenfalls sehr bewusst getroffen - dieser Code wurde sehr bewusst hinzugefügt. Ich weiß: Ich arbeite an diesem Team. Darüber hinaus wurde dieser Code als Teil einer Anfrage von einem Benutzer auf "Meta" freigegeben, nachdem ich einen [Stackoverflow-Fehler durch dieses Problem behoben] (http://meta.stackexchange.com/q/169356) behoben. Tl; Dr: Ihre eigene Frage zu beantworten ist ausdrücklich OK, solange die Frage und die Antwort gut gebildet und passend sind. –

Antwort

21

Die Weise, die ich angeheftet habe, ist, die zugrunde liegenden Server-Variablen zu betrachten; die URL Variable enthält einen decodierten Wert; Die Variable QUERY_STRING enthält die noch codierte Abfrage. Wir können nicht einfach anrufen encodieren auf dem URL Teil, denn das enthält auch das ursprüngliche / etc in ihrer ursprünglichen Form - wenn wir blind die gesamte Sache codieren wir unerwünschte %2f Werte bekommen; Allerdings kann es auseinander ziehen und problematische Fälle:

private static readonly Regex simpleUrlPath = new Regex("^[-a-zA-Z0-9_/]*$", RegexOptions.Compiled); 
private static readonly char[] segmentsSplitChars = { '/' }; 
// ^^^ avoids lots of gen-0 arrays being created when calling .Split 
public static Uri GetRealUrl(this HttpRequest request) 
{ 
    if (request == null) throw new ArgumentNullException("request"); 
    var baseUri = request.Url; // use this primarily to avoid needing to process the protocol/authority 
    try 
    { 
     var vars = request.ServerVariables; 
     var url = vars["URL"]; 
     if (string.IsNullOrEmpty(url) || simpleUrlPath.IsMatch(url)) return baseUri; // nothing to do - looks simple enough even for IIS 

     var query = vars["QUERY_STRING"]; 
     // here's the thing: url contains *decoded* values; query contains *encoded* values 

     // loop over the segments, encoding each separately 
     var sb = new StringBuilder(url.Length * 2); // allow double to be pessimistic; we already expect trouble 
     var segments = url.Split(segmentsSplitChars); 
     foreach (var segment in segments) 
     { 
      if (segment.Length == 0) 
      { 
       if(sb.Length != 0) sb.Append('/'); 
      } 
      else if (simpleUrlPath.IsMatch(segment)) 
      { 
       sb.Append('/').Append(segment); 
      } 
      else 
      { 
       sb.Append('/').Append(HttpUtility.UrlEncode(segment)); 
      } 
     } 
     if (!string.IsNullOrEmpty(query)) sb.Append('?').Append(query); // query is fine; nothing needing 
     return new Uri(baseUri, sb.ToString()); 
    } 
    catch (Exception ex) 
    { // if something unexpected happens, default to the broken ASP.NET handling 
     GlobalApplication.LogException(ex); 
     return baseUri; 
    } 
} 
+2

Ich liebe diesen Code, Marc +1. – Brian

Verwandte Themen