2010-02-08 16 views
12

मैं एक यूआरएल पुनर्लेखन आवेदन पर एक बग को ट्रैक कर रहा हूं। बग क्वेरीस्ट्रिंग में कुछ diacritic पात्रों पर एक एन्कोडिंग समस्या के रूप में दिखाई दिया।Request.Url.Query और Request.QueryString के बीच क्या अंतर है?

मूल रूप से, समस्या यह है कि एक अनुरोध जो मूल रूप से था /search.aspx?search=heřmánek की एक क्वेरी स्ट्रिंग "खोज = वह% सी 5% -99% C3% a1nek"

सही मान के साथ फिर से लिखा जा रहा रहा था (कुछ अलग, कामकाजी कोड का उपयोग करके) क्वेरीस्ट्रिंग का एक पुनःलेख था "खोज = वह% u0159m% u00e1nek"

दो तारों के बीच अंतर नोट करें। हालांकि, यदि आप दोनों पोस्ट करते हैं तो आप देखेंगे कि यूआरएल एन्कोडिंग एक ही स्ट्रिंग को पुन: उत्पन्न करता है। यह तब तक नहीं है जब तक कि आप संदर्भ का उपयोग न करें। एन्कोडिंग ब्रेक करने वाले फ़ंक्शन को लिखें। टूटी हुई स्ट्रिंग 'heÅmánek' (Request.QueryString ["Search"] का उपयोग करके और कार्यरत स्ट्रिंग 'heřmánek' लौटाती है। यह परिवर्तन पुनः लिखने के लिए कॉल के बाद होता है।

मैंने इसे एक सेट पर खोज लिया Request.QueryString (काम कर रहे) का उपयोग करके कोड का अनुरोध और दूसरा Request.Url.Query (request.Url एक यूरी इंस्टेंस देता है)।

जबकि मैंने बग का काम किया है, वहां मेरी समझ में एक छेद है, इसलिए यदि कोई भी अंतर जानता है, मैं पाठ के लिए तैयार हूं।

उत्तर

2

आपका प्रश्न वास्तव में मेरी रुचि बढ़ाता है, इसलिए मैंने पिछले घंटे या उससे कुछ के लिए कुछ पढ़ा है। मैं बिल्कुल सकारात्मक नहीं हूं मुझे जवाब मिला है , लेकिन मैं इसे बाहर फेंक देंगे यह देखने के लिए कि आप क्या सोचते हैं।

जो मैंने अभी तक पढ़ा है, से Request.QueryString वास्तव में "सर्वर Variables संग्रह में QUERY_STRING चर का एक विश्लेषण संस्करण है" [reference], जहां Request.Url है (जैसा कि आपने बताया है) कच्चे यूआरएल में encapsulated उरी वस्तु this article के अनुसार, उरी क्लास 'कन्स्ट्रक्टर "... [url स्ट्रिंग] को पार करता है, इसे कैननिकल प्रारूप में रखता है, और किसी भी आवश्यक एस्कोडिंग को बनाता है।"

इसलिए, ऐसा प्रतीत होता है कि Request.QueryString ServerVariables कन्स्ट्रक्टर से "QUERY_STRING" चर को पार्स करने के लिए एक अलग फ़ंक्शन का उपयोग करता है। यह समझाएगा कि आप दोनों के बीच का अंतर क्यों देखते हैं। अब, कस्टम पार्सिंग फ़ंक्शन द्वारा अलग-अलग एन्कोडिंग विधियों का उपयोग क्यों किया जाता है और उरी ऑब्जेक्ट का पार्सिंग फ़ंक्शन पूरी तरह से मेरे बाहर है। हो सकता है कि aspnet_isapi DLL पर थोड़ा और अधिक जानकारी प्राप्त हो, उस प्रश्न के साथ कुछ जवाब प्रदान कर सके।

वैसे भी, उम्मीद है कि मेरी पोस्ट समझ में आता है। एक तरफ ध्यान दें, मैं एक और संदर्भ जोड़ना चाहता हूं जो कुछ बहुत ही गहन और रोचक पढ़ने के लिए भी प्रदान किया गया है: http://download.microsoft.com/download/6/c/a/6ca715c5-2095-4eec-a56f-a5ee904a1387/Ch-12_HTTP_Request_Context.pdf

+0

दोनों गुण एक ही एन्कोडेड स्ट्रिंग को अधिकांश समय लौटाते हैं - कन्स्ट्रक्टर और पार्सिंग इस मामले में अप्रासंगिक हैं। यह फिर से लिखने के बाद है कि उरी के एन्कोडिंग में बदलाव आया है। – zombat

+0

शायद आपके उत्तर और गर्भ संयुक्त नीचे जवाब सच है। शायद यह मामला है कि एक लैटिन -1 कोड का उपयोग करते हुए यूआरएल एन्कोडिंग को संरक्षित करता है और दूसरा यूटीएफ -8 का उपयोग करता है। –

3

जो आपने "टूटा" एन्कोडेड स्ट्रिंग के रूप में इंगित किया है वास्तव में मानकों के अनुसार सही एन्कोडिंग है। जिसे आपने "सही" एन्कोडिंग के रूप में इंगित किया है, वह (मुझे विश्वास है कि यह यूटीएफ -16 एन्कोडिंग को इंगित करने वाला है) के प्रारूप को अनुमति देने के लिए विनिर्देशों के लिए गैर-मानक एक्सटेंशन का उपयोग कर रहा है।

किसी भी मामले में, "टूटा" एन्कोडेड स्ट्रिंग ठीक है। आप निम्न कोड का उपयोग यह जांचने के लिए कर सकते हैं कि:

Uri uri = new Uri("http://www.example.com/test.aspx?search=heřmánek"); 
Console.WriteLine(uri.Query); 
Console.WriteLine(HttpUtility.UrlDecode(uri.Query)); 

ठीक काम करता है। हालांकि ... एक कूबड़ पर, मैं UrlDecode एक लैटिन -1 कोड पृष्ठ पर निर्दिष्ट के साथ, की कोशिश की डिफ़ॉल्ट के बजाय UTF-8:

Console.WriteLine(HttpUtility.UrlDecode(uri.Query, 
      Encoding.GetEncoding("iso-8859-1"))); 

... और मुझे बुरा मूल्य आपके द्वारा निर्दिष्ट, 'मिला heÅmánek '।दूसरे शब्दों में, ऐसा लगता है कि HttpContext.RewritePath() पर कॉल यूटीएफ -8 की बजाय लैटिन -1 कोडपेज का उपयोग करने के लिए यूरेनेंकोडिंग/डिकोडिंग को बदलता है, जो यूआरएलएनकोड/डिकोड विधियों द्वारा उपयोग किया जाने वाला डिफ़ॉल्ट एन्कोडिंग है।

यदि आप मुझसे पूछें तो यह एक बग जैसा दिखता है। आप परावर्तक में RewritePath() कोड देख सकते हैं और देख सकते हैं कि यह निश्चित रूप से क्वेरीस्ट्रिंग के साथ खेल रहा है - इसे सभी प्रकार के आभासी पथ कार्यों के आसपास पास करना, और कुछ अप्रबंधित आईआईएस कोड के लिए।

मुझे आश्चर्य है कि रास्ते में कहीं भी, अनुरोध वस्तु के मूल में उरी गलत कोडपेज के साथ छेड़छाड़ की जाती है? यह समझाएगा कि क्यों Request.Querystring (जो कि HTTP शीर्षलेखों से केवल कच्चे मूल्य हैं) सही होगा, जबकि उरीकृतियों के लिए गलत एन्कोडिंग का उपयोग करते हुए उरी गलत होगा।

+0

मुझे खुशी है कि आपको लगता है कि यह एक बग है। मैं काम नहीं कर सकता कि यह व्यवहार इस तरह क्यों होगा। –

0

मैंने पिछले दिन या तो कुछ शोध किया है और मुझे लगता है कि मेरे पास इस बारे में कुछ जानकारी है।

जब आप Request.Querystring या HttpUtility.UrlDecode (या एन्कोड) का उपयोग करते हैं तो यह web.config (या .config पदानुक्रम 'के तत्व में निर्दिष्ट एन्कोडिंग (विशेष रूप से अनुरोध एन्कोडिंग विशेषता) का उपयोग कर रहा है। टी निर्दिष्ट) --- एन्कोडिंग नहीं। डीफॉल्ट जो आपके सर्वर के लिए डिफ़ॉल्ट एन्कोडिंग है।

जब आपके पास यूटीएफ -8 में एन्कोडिंग सेट होता है, तो एक यूनिकोड चरित्र को 2% xx हेक्स मानों के रूप में एन्कोड किया जा सकता है। पूरे मूल्य को देखते समय इसे भी डीकोड किया जाएगा।

यदि आप यूआरएल की तुलना में एक अलग एन्कोडिंग के साथ UrlDecoding हैं, तो आपको एक अलग परिणाम मिलेगा।

के बाद से HttpUtility.UrlEncode और UrlDecode कोई एन्कोडिंग पैरामीटर ले जा सकते हैं, अपने आकर्षक एक एएनएसआई कोडपेज का उपयोग कर सांकेतिक शब्दों में बदलना करने की कोशिश करने के लिए है, लेकिन UTF-8 यदि आप ब्राउज़र समर्थन जाने के लिए सही रास्ता है (जाहिरा तौर पर पुराने संस्करणों नहीं है यूटीएफ -8 का समर्थन करें)। आपको बस यह सुनिश्चित करने की ज़रूरत है कि ठीक से सेट किया गया है और दोनों पक्ष ठीक काम करेंगे।

UTF-8 डिफ़ॉल्ट एन्कोडिंग लगता है: पता लगाने के लिए this.ContentEncoding में ले जाता है (.net परावर्तक System.Web.HttpRequest से)

internal Encoding QueryStringEncoding 
{ 
    get 
    { 
     Encoding contentEncoding = this.ContentEncoding; 
     if (!contentEncoding.Equals(Encoding.Unicode)) 
     { 
      return contentEncoding; 
     } 
     return Encoding.UTF8; 
    } 
} 

पथ के बाद (भी HttpRequest)

public Encoding ContentEncoding 
{ 
    get 
    { 
     if (!this._flags[0x20] || (this._encoding == null)) 
     { 
      this._encoding = this.GetEncodingFromHeaders(); 
      if (this._encoding == null) 
      { 
       GlobalizationSection globalization = RuntimeConfig.GetLKGConfig(this._context).Globalization; 
       this._encoding = globalization.RequestEncoding; 
      } 
      this._flags.Set(0x20); 
     } 
     return this._encoding; 
    } 
    set 
    { 
     this._encoding = value; 
     this._flags.Set(0x20); 
    } 
} 

Request.Url.Quer और Request.QueryString betwen अंतर पर अपने विशिष्ट सवाल का जवाब करने के लिए ... यहाँ है कैसे HttpRequest अपने यूआरएल संपत्ति बनाता है:

public Uri Url 
{ 
    get 
    { 
     if ((this._url == null) && (this._wr != null)) 
     { 
      string queryStringText = this.QueryStringText; 
      if (!string.IsNullOrEmpty(queryStringText)) 
      { 
       queryStringText = "?" + HttpEncoder.CollapsePercentUFromStringInternal(queryStringText, this.QueryStringEncoding); 
      } 
      if (AppSettings.UseHostHeaderForRequestUrl) 
      { 
       string knownRequestHeader = this._wr.GetKnownRequestHeader(0x1c); 
       try 
       { 
        if (!string.IsNullOrEmpty(knownRequestHeader)) 
        { 
         this._url = new Uri(this._wr.GetProtocol() + "://" + knownRequestHeader + this.Path + queryStringText); 
        } 
       } 
       catch (UriFormatException) 
       { 
       } 
      } 
      if (this._url == null) 
      { 
       string serverName = this._wr.GetServerName(); 
       if ((serverName.IndexOf(':') >= 0) && (serverName[0] != '[')) 
       { 
        serverName = "[" + serverName + "]"; 
       } 
       this._url = new Uri(this._wr.GetProtocol() + "://" + serverName + ":" + this._wr.GetLocalPortAsString() + this.Path + queryStringText); 
      } 
     } 
     return this._url; 
    } 
} 

आप देख सकते हैं कि यह डिकोडिंग करने के लिए HttpEncoder क्लास का उपयोग कर रहा है, लेकिन यह एक ही QueryStringEncoding मान का उपयोग करता है।

चूंकि मैं पहले से ही बहुत सारे कोड पोस्ट कर रहा हूं और कोई भी .NET परावर्तक प्राप्त कर सकता है, मैं बाकी को स्निपेट करने जा रहा हूं। QueryString प्रॉपर्टी HttpValueCollection से आता है जो अंततः HttpUtility.UrlDecode (ऊपर QueryStringEncoding मान सेट के साथ) को कॉल करने के लिए FillFromEncodedBytes विधि का उपयोग करता है, जो अंततः HttpEncoder को डीकोड करने के लिए कहते हैं। वे क्वेरीस्ट्रिंग के वास्तविक बाइट्स को डीकोड करने के लिए विभिन्न पद्धतियों का उपयोग करते प्रतीत होते हैं, लेकिन ऐसा करने के लिए वे एन्कोडिंग का उपयोग करते हैं, ऐसा लगता है।

यह मेरे लिए दिलचस्प है कि एचटीपीएनकोडर में इतने सारे काम हैं जो एक ही काम करते हैं, इसलिए संभव है कि उन तरीकों में मतभेद हैं जो किसी समस्या का कारण बन सकते हैं।

संबंधित मुद्दे