即使路径中有百分比编码的部分,我怎样才能可靠地获得实际的URL?

IIS和ASP.NET(MVC)在使用路径中具有%-encoding的URL时(而不是查询字符串;查询字符串很好) 有一些小故障 。 我怎么能绕过这个? 即如何获取所请求的实际URL?

例如,如果我导航到/x%3Fa%3Db并且(单独)导航到/x%3Fa%3Db /x?a=b – 它们都将.Request.Url报告为/x?a=b – 因为路径中的编码数据是报错了。

我解决这个问题的方法是查看底层服务器变量; URL变量包含解码值; QUERY_STRING变量包含仍然编码的查询。 我们不能只在URL部分调用encode ,因为它还包含原始forms的orignal / etc – 如果我们盲目地编码整个东西,我们将获得不需要的%2f值; 但是,可以将它拆开并发现有问题的情况:

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