1+ using System . Collections . Specialized ;
12using System . Text ;
3+ using System . Web ;
24
35namespace FluentRest ;
46
@@ -57,8 +59,8 @@ public class UrlBuilder
5759 { "xmpp" , null }
5860 } ;
5961
60- private readonly IDictionary < string , ICollection < string > > _query ;
61- private readonly IList < string > _path ;
62+ private readonly NameValueCollection _query ;
63+ private readonly List < string > _path ;
6264 private readonly string _schemeDelimiter ;
6365
6466 private string _fragment ;
@@ -73,7 +75,7 @@ public class UrlBuilder
7375 /// </summary>
7476 public UrlBuilder ( )
7577 {
76- _query = new Dictionary < string , ICollection < string > > ( ) ;
78+ _query = new NameValueCollection ( ) ;
7779 _path = new List < string > ( ) ;
7880 _fragment = string . Empty ;
7981 _host = "localhost" ;
@@ -175,7 +177,7 @@ public UrlBuilder(Uri uri) : this()
175177 /// <value>
176178 /// The query string dictionary information included in the Url.
177179 /// </value>
178- public IDictionary < string , ICollection < string > > Query => _query ;
180+ public NameValueCollection Query => _query ;
179181
180182 /// <summary>
181183 /// Gets the fragment portion of the Url.
@@ -429,10 +431,7 @@ public UrlBuilder AppendQuery(string name, string value)
429431 if ( name == null )
430432 throw new ArgumentNullException ( nameof ( name ) ) ;
431433
432- var v = value ?? string . Empty ;
433-
434- var list = Query . GetOrAdd ( name , n => new List < string > ( ) ) ;
435- list . Add ( v ) ;
434+ Query . Add ( name , value ?? string . Empty ) ;
436435
437436 return this ;
438437 }
@@ -632,23 +631,20 @@ private void WriteQueryString(StringBuilder builder)
632631 builder . Append ( '?' ) ;
633632
634633 int start = builder . Length ;
635- foreach ( var pair in Query )
636- {
637- var key = pair . Key ;
638- key = Uri . EscapeDataString ( key ) ;
639634
640- var values = pair . Value . ToList ( ) ;
635+ foreach ( var key in Query . AllKeys )
636+ {
637+ var k = Uri . EscapeDataString ( key ?? string . Empty ) ;
641638
642- foreach ( var value in values )
639+ foreach ( var value in Query . GetValues ( key ) )
643640 {
644641 if ( builder . Length > start )
645642 builder . Append ( '&' ) ;
646643
647- var v = value ;
648- v = Uri . EscapeDataString ( v ) ;
644+ var v = Uri . EscapeDataString ( value ?? string . Empty ) ;
649645
650646 builder
651- . Append ( key )
647+ . Append ( k )
652648 . Append ( '=' )
653649 . Append ( v ) ;
654650 }
@@ -690,65 +686,8 @@ private void ParseQueryString(string s)
690686 if ( string . IsNullOrEmpty ( s ) )
691687 return ;
692688
693- int l = s . Length ;
694- int i = 0 ;
695-
696- // remove leading ?
697- if ( s [ 0 ] == '?' )
698- i = 1 ;
699-
700- while ( i < l )
701- {
702- // find next & while noting first = on the way (and if there are more)
703- int si = i ;
704- int ti = - 1 ;
705-
706- while ( i < l )
707- {
708- char ch = s [ i ] ;
709-
710- if ( ch == '=' )
711- {
712- if ( ti < 0 )
713- ti = i ;
714- }
715- else if ( ch == '&' )
716- {
717- break ;
718- }
719-
720- i ++ ;
721- }
722-
723- // extract the name / value pair
724- string name = null ;
725- string value = null ;
726-
727- if ( ti >= 0 )
728- {
729- name = s . Substring ( si , ti - si ) ;
730- value = s . Substring ( ti + 1 , i - ti - 1 ) ;
731- }
732- else
733- {
734- value = s . Substring ( si , i - si ) ;
735- }
736-
737- // decode
738- name = string . IsNullOrEmpty ( name ) ? string . Empty : Uri . UnescapeDataString ( name ) ;
739- value = string . IsNullOrEmpty ( value ) ? string . Empty : Uri . UnescapeDataString ( value ) ;
740-
741- // add name / value pair to the collection
742- if ( ! string . IsNullOrEmpty ( name ) )
743- AppendQuery ( name , value ) ;
744-
745- // trailing '&'
746-
747- //if (i == l-1 && s[i] == '&')
748- // base.Add(null, String.Empty);
749-
750- i ++ ;
751- }
689+ var result = HttpUtility . ParseQueryString ( s ) ;
690+ Query . Add ( result ) ;
752691 }
753692
754693 private void ParsePath ( string s )
0 commit comments