2013-02-27 25 views
17

IIS và ASP.NET (MVC) has some glitches khi làm việc với các url có mã hóa% trong đường dẫn (không phải chuỗi truy vấn; chuỗi truy vấn là tốt). Làm sao để tôi có được xung quanh này? tức là làm cách nào tôi có thể nhận được URL thực tế đã được yêu cầu?Làm cách nào để nhận được URL thực tế một cách đáng tin cậy, ngay cả khi có các phần được mã hóa phần trăm trong đường dẫn?

Ví dụ, nếu tôi hướng đến /x%3Fa%3Db và (riêng) để /x?a=b - cả trong số họ báo cáo .Request.Url như /x?a=b - vì dữ liệu được mã hóa trong đường dẫn được báo cáo không chính xác.

+0

Trong khi suy nghĩ được đánh giá cao, StackOverflow là * không * một trang web đoạn trích hoặc một nơi để đăng những thứ bạn tìm ra, tức là blog. Dấu thời gian của câu hỏi và câu trả lời của bạn cho biết rằng bạn đã đến đây sẵn sàng đăng cả hai. Vui lòng chỉ đăng câu hỏi mà bạn thực sự cần trợ giúp. Có nhiều cách thích hợp hơn để chỉ chia sẻ thông tin với cộng đồng. –

+29

@Chris [Tự trả lời luôn được chấp nhận] (http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/). Quyết định cho phép trả lời * như một phần của yêu cầu * cũng được thực hiện rất thận trọng - mã đó đã được thêm vào rất có chủ ý. Tôi biết: Tôi làm việc cho đội đó. Hơn nữa, mã này đã được chia sẻ như là một phần của yêu cầu của người dùng về "meta" sau khi tôi sửa lỗi [stackoverflow bug do vấn đề này] (http://meta.stackexchange.com/q/169356). Tl; Tiến sĩ: trả lời câu hỏi của riêng bạn là hoàn toàn OK, miễn là câu hỏi và câu trả lời được hình thành và phù hợp. –

Trả lời

21

Cách tôi đã giải quyết vấn đề này là xem xét các biến máy chủ cơ bản; biến số URL chứa giá trị được giải mã; biến số QUERY_STRING chứa truy vấn được mã hóa tĩnh. Chúng tôi không thể chỉ cần mã hóa trên phần URL, bởi vì nó cũng chứa số / v.v ... trong dạng ban đầu của chúng - nếu chúng tôi mã hóa một cách mù quáng toàn bộ, chúng tôi sẽ nhận giá trị %2f không mong muốn; tuy nhiên, có thể kéo nó ra xa và phát hiện các trường hợp có vấn đề:

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

Tôi thích mã này, Marc +1. – Brian

Các vấn đề liên quan