URL encoding in .NET 2.0

by Jörg Jooss 18. September 2005 02:59

The .NET 2.0 BCL offers various means to create URL encoded strings. One can use System.Uri or System.UriBuilder to create RFC 2396 compliant URLs, or System.Web.HttpUtiliy.UrlEncode(System.String, System.Text.Encoding) to URL encode individual strings. Unfortunately, neither System.Uri nor System.UriBuilder allow one to specify a character encoding for URL encoding. Both classes use UTF-8 exclusively. System.Uri is nonetheless capable of representing URIs whose query strings are based on encodings other than UTF-8, if the user creates a System.Uri from an already URL encoded string. System.Web.HttpUtiliy.UrlEncode(System.String, System.Text.Encoding) on the other hand cannot encode entire query strings, only individual names or values, so a developer must parse query string and encode each name or value individually.

Enter UrlEncoder. This class is able to encode or reencode System.Uri and System.String objects with arbitrary character encodings. Enjoy. Smile

Note for Firefox users: The formatted code below may display scroll bars below some of the longer lines. To get rid of them, reduce the pixel size for fixed width fonts — sorry!


   1:  using System;
   2:  using System.Collections.Specialized;
   3:  using System.Text;
   4:  using System.Web;
   5:   
   6:  namespace JoergJooss.SharpAgent.Http
   7:  {
   8:      /// <summary>
   9:      /// Provides URL encoding capabilities for <see cref="System.Uri"/> and 
  10:      /// <see cref="System.String"/> using arbitrary character encodings.
  11:      /// </summary>
  12:      /// <remarks>
  13:      /// <para>
  14:      /// The .NET BCL offers various means to create URL encoded strings
  15:      /// or URI objects with query strings. One can use <see cref="System.Uri"/> or
  16:      /// <see cref="System.UriBuilder"/> to create RFC 2396 compliant
  17:      /// URLs, or <see cref="System.Web.HttpUtiliy.UrlEncode(System.String, System.Text.Encoding)"/> 
  18:      /// to URL encode individual strings. Unfortunately, neither 
  19:      /// <see cref="System.Uri"/> nor <see cref="System.UriBuilder"/> allow one 
  20:      /// to specify a character encoding for URL encoding. Both classes use 
  21:      /// UTF-8 exclusively. <see cref="System.Uri"/> is nonetheless capable
  22:      /// of representing URIs whose query strings are based on encodings
  23:      /// other than UTF-8, if the user creates a <see cref="System.Uri"/> from 
  24:      /// an already URL encoded string. 
  25:      /// <see cref="System.Web.HttpUtiliy.UrlEncode(System.String, System.Text.Encoding)"/>
  26:      /// on the other hand cannot encode entire query strings, only individual
  27:      /// names or values. <see cref="JoergJooss.SharpAgent.Http.UrlEncoder"/>
  28:      /// is able to encode or reencode <see cref="System.Uri"/> and 
  29:      /// <see cref="System.String"/> objects with arbitrary character encodings.
  30:      /// </para>
  31:      /// <para>
  32:      /// <see cref="JoergJooss.SharpAgent.Http.UrlEncoder"/> instances are
  33:      /// immutable. All non-inherited instance methods are thread safe.
  34:      /// </para>
  35:      /// </remarks>
  36:      public sealed class UrlEncoder
  37:      {
  38:          private readonly Encoding encoding;
  39:   
  40:          private static readonly UrlEncoder utf8;
  41:          private static readonly UrlEncoder latin1;
  42:          private static readonly UrlEncoder latin9;
  43:   
  44:          static UrlEncoder()
  45:          {
  46:              utf8 = new UrlEncoder(Encoding.UTF8);
  47:              latin1 = new UrlEncoder(Encoding.GetEncoding(28591));
  48:              latin9 = new UrlEncoder(Encoding.GetEncoding(28605));
  49:          }
  50:   
  51:          /// <summary>
  52:          /// Initializes a new instance of the 
  53:          /// <see cref="JoergJooss.SharpAgent.Http.UrlEncoder"/> class 
  54:          /// that uses the specified character encoding. 
  55:          /// </summary>
  56:          /// <param name="encoding">An encoding.</param>
  57:          /// <exception cref="System.ArgumentNullException">
  58:          /// encoding is <c>null</c>.
  59:          /// </exception>
  60:          public UrlEncoder(Encoding encoding)
  61:          {
  62:              if (encoding == null)
  63:              {
  64:                  throw new ArgumentNullException("encoding");
  65:              }
  66:   
  67:              this.encoding = encoding;
  68:          }
  69:   
  70:          /// <summary>
  71:          /// Gets the encoding used by this instance.
  72:          /// </summary>
  73:          /// <value>
  74:          /// A <see cref="System.Text.Encoding"/> object representing the 
  75:          /// character encoding that is used by this instance.
  76:          /// </value>
  77:          public Encoding Encoding
  78:          {
  79:              get { return encoding; }
  80:          }
  81:   
  82:          /// <summary>
  83:          /// Gets a <see cref="JoergJooss.SharpAgent.Http.UrlEncoder"/> for the
  84:          /// Latin 1 (ISO-8859-1) character encoding.
  85:          /// </summary>
  86:          public static UrlEncoder Latin1
  87:          {
  88:              get { return latin1; }
  89:          }
  90:   
  91:          /// <summary>
  92:          /// Gets a <see cref="JoergJooss.SharpAgent.Http.UrlEncoder"/> for 
  93:          /// the Latin 9 (ISO-8859-15) character encoding.
  94:          /// </summary>
  95:          public static UrlEncoder Latin9
  96:          {
  97:              get { return latin9; }
  98:          }
  99:   
 100:          /// <summary>
 101:          /// Gets a <see cref="JoergJooss.SharpAgent.Http.UrlEncoder"/> for 
 102:          /// the UTF-8 character encoding.
 103:          /// </summary>
 104:          public static UrlEncoder Utf8
 105:          {
 106:              get { return utf8; }
 107:          }
 108:   
 109:          /// <summary>
 110:          /// Gets the Base Class Library's default Encoding object
 111:          /// used by <see cref="System.Uri"/> and 
 112:          /// <see cref="System.UriBuilder"/>.
 113:          /// </summary>
 114:          internal static Encoding DefaultUriEncoding
 115:          {
 116:              get { return Encoding.UTF8; }
 117:          }
 118:   
 119:          /// <summary>
 120:          /// Creates a new Uri object from an existing Uri but
 121:          /// using the UrlEncoder's character encoding.
 122:          /// </summary>
 123:          /// <param name="uri">A URI.</param>
 124:          /// <returns>The URI whose str string is encoded with
 125:          /// the UrlEncoder's character encoding.</returns>
 126:          /// <exception cref="System.ArgumentNullException">
 127:          /// uri is <c>null</c>.
 128:          /// </exception>
 129:          public Uri Encode(Uri uri)
 130:          {
 131:              if (uri == null)
 132:              {
 133:                  throw new ArgumentNullException("uri");
 134:              }
 135:   
 136:              UriBuilder ub = new UriBuilder(uri);
 137:              ub.Query = EncodeString(uri.Query);
 138:   
 139:              return ub.Uri;
 140:          }
 141:   
 142:          /// <summary>
 143:          /// Creates a new Uri object from a string 
 144:          /// using the UrlEncoder's character encoding.
 145:          /// </summary>
 146:          /// <param name="uri">A URI.</param>
 147:          /// <returns>The URI whose str string is encoded with
 148:          /// the UrlEncoder's character encoding.</returns>
 149:          /// <exception cref="System.ArgumentNullException">
 150:          /// uri is <c>null</c>.
 151:          /// </exception>
 152:          public Uri Encode(string uri)
 153:          {
 154:              return Encode(new Uri(uri));
 155:          }
 156:   
 157:          /// <summary>
 158:          /// URL encodes a string with the UrlEncoder's encoding.
 159:          /// </summary>
 160:          /// <remarks>
 161:          /// <paramref name="str"/> is URL decoded before it is being
 162:          /// encoded. This method assumes UTF-8 as original character 
 163:          /// encoding.
 164:          /// </remarks>
 165:          /// <param name="str">A string.</param>
 166:          /// <returns>A URL encoded representation of <paramref name="str"/>
 167:          /// using the UrlEncoder's encoding.
 168:          /// </returns>
 169:          public string EncodeString(string str)
 170:          {
 171:              return EncodeString(str, null);
 172:          }
 173:   
 174:          /// <summary>
 175:          /// URL encodes a (potentially already URL encoded) string  
 176:          /// with the UrlEncoder's encoding.
 177:          /// </summary>
 178:          /// <remarks>
 179:          /// <paramref name="str"/> is URL decoded before it is being
 180:          /// encoded, using <paramref name="enc"/> as original character 
 181:          /// encoding.
 182:          /// </remarks>
 183:          /// <param name="str">A string.</param>
 184:          /// <param name="enc">The original character encoding. If <c>null</c> 
 185:          /// is passed, UTF-8 is assumed. </param>
 186:          /// <returns>A URL encoded representation of <paramref name="str"/>
 187:          /// using the UrlEncoder's encoding.
 188:          /// </returns>
 189:          public string EncodeString(string str, Encoding enc)
 190:          {
 191:              if (str == null)
 192:              {
 193:                  throw new ArgumentNullException("uri");
 194:              }
 195:   
 196:              if (str == String.Empty)
 197:              {
 198:                  return String.Empty;
 199:              }
 200:   
 201:              StringBuilder sb = new StringBuilder(str.Length);
 202:              NameValueCollection coll = HttpUtility.ParseQueryString(
 203:                  str, 
 204:                  enc != null ? enc : DefaultUriEncoding);
 205:   
 206:              foreach (string key in coll)
 207:              {
 208:                  string encodedKey = HttpUtility.UrlEncode(key, Encoding);
 209:                  string encodedValue = HttpUtility.UrlEncode(coll[key], Encoding);
 210:                  sb.AppendFormat("{0}={1}&", encodedKey, encodedValue);
 211:              }
 212:   
 213:              sb.Length -= 1;
 214:              return sb.ToString();
 215:          }
 216:      }
 217:  }

Tags: ,

.NET | ASP.NET

Comments (2) -

software developer
software developer
8/21/2009 6:55:50 AM #

Quite inspiring,

I opend it in fire fox and  the code was harrible then I read your note and it was fix, thanks for paying attention to the detail

Thanks for writing, most people don't bother.

Pferdemarkt
Pferdemarkt United States
2/16/2010 1:02:32 PM #

Wooo! clever approach in the code above.compiled and saved in my reserved classes kit..Thanks alot..

Comments are closed

Page List

RecentPosts

Disclaimer

The posts on this weblog are provided "AS IS" with no warranties, and confer no rights. The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

 

© Copyright 2010, Jörg Jooss