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;
}
}
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. –
@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. –