Il modo in cui ho virato questo è quello di guardare ai server-variabili sottostanti; la variabile URL
contiene un valore decodificato; la variabile QUERY_STRING
contiene la query ancora codificata. Non possiamo semplicemente chiamare codificare sulla parte URL
, perché anche questo contiene l'originale /
ecc nella loro forma originale - se codifichiamo ciecamente l'intera cosa otterremo valori indesiderati %2f
; tuttavia, può separarlo e individuare casi problematici:
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;
}
}
fonte
2013-02-27 16:35:57
Mentre il pensiero è apprezzato, StackOverflow è * non * un sito frammento o un luogo per pubblicare le cose che capisci, cioè un blog. I timestamp delle vostre domande e risposte indicano che siete venuti qui pronti a postare entrambi. Si prega di inviare solo domande con cui hai veramente bisogno di aiuto. Esistono modi più appropriati per condividere le informazioni con la comunità. –
@ Chris [Self segreteria è sempre stato accettabile] (http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/). Anche la decisione di autorizzare la risposta * come parte della richiesta * è stata presa in modo molto deliberato - quel codice è stato aggiunto molto intenzionalmente. Lo so: lavoro su quella squadra. Inoltre, questo codice è stato condiviso come parte di una richiesta da parte di un utente su "meta" dopo aver corretto un [errore StackOverflow causato da questo problema] (http://meta.stackexchange.com/q/169356). Tl; Dr: rispondere alla tua domanda è esplicitamente OK, a patto che la domanda e la risposta siano ben formate e appropriate. –