Safe Base64 Url in ASP .NET

Posted in Misc on September 28th, 2009 by taswar

So came into a problem of url encoding in IIS 7 where it does not like “+”, “/” in the Url. Basically a Url that looks like of like this

http://fake.abc/TIRlcEq0umjO6uJqtqvnkUGntUzv19rK+8mcvPK5qL1bwEZtEUqTlc3iF/TomuXU746Il5IF2iN9SeYuYDqt6SQzfdrv+Ltug2KZteKlYawc=

I know you may say what is this??? Its actually some kind of encrypted data that is in base64, but since IIS 7 does not like “+” or “/” even if its url encoded.

So I made a Utility class string extension method that just simply replaces the characters with “-” and “_”

Here is the code so maybe someday it would help you out also.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static class SafeBase64UrlEncoder
	{
		private const string Plus = "+";
		private const string Minus = "-";
		private const string Slash = "/";
		private const string Underscore = "_";
		private const string EqualSign = "=";
		private const string Pipe = "|";
		private static readonly IDictionary<string, string> _mapper;
 
 
		static SafeBase64UrlEncoder()
		{
			_mapper = new Dictionary<string, string> {{Plus, Minus}, {Slash, Underscore}, {EqualSign, Pipe}};
		}
 
		/// <summary>
		/// Encode the base64 to safeUrl64
		/// </summary>
		/// <param name="base64Str"></param>
		/// <returns></returns>
		public static string EncodeBase64Url(this string base64Str)
		{
			if (string.IsNullOrEmpty(base64Str))
				return base64Str;
 
			foreach (var pair in _mapper)
			{
				base64Str = base64Str.Replace(pair.Key, pair.Value);
			}
 
			return base64Str;
		}
 
 
		/// <summary>
		/// Decode the Url back to original base64
		/// </summary>
		/// <param name="safe64Url"></param>
		/// <returns></returns>
		public static string DecodeBase64Url(this string safe64Url)
		{
 
			if (string.IsNullOrEmpty(safe64Url))
				return safe64Url;
 
			foreach (var pair in _mapper)
			{
				safe64Url = safe64Url.Replace(pair.Value, pair.Key);
			}
 
			return safe64Url;
		}
	}

And always there should be a test for it.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
[TestFixture]
	public class SafeBase64UrlTests
	{
 
		[Test]
		public void Encode64Url_Should_Replace_Plus_With_Minus()
		{
			var str = "+".EncodeBase64Url();
 
			Assert.That(str.Equals("-"),Is.True);
		}
 
 
		[Test]
		public void Encode64Url_Should_Replace_ThreePlus_With_ThreeMinus()
		{
			var str = "+++".EncodeBase64Url();
 
			Assert.That(str.Equals("---"), Is.True);
		}
 
		[Test]
		public void Decode64Url_Should_Replace_Minus_With_Plus()
		{
			var str = "-".DecodeBase64Url();
 
			Assert.That(str.Equals("+"), Is.True);
		}
 
		[Test]
		public void Decode64Url_Should_Replace_ThreeMinus_With_ThreePlus()
		{
			var str = "---".DecodeBase64Url();
 
			Assert.That(str.Equals("+++"), Is.True);
		}
 
 
		[Test]
		public void Encode64Url_Should_Replace_Slash_With_Underscore()
		{
			var str = "/".EncodeBase64Url();
 
			Assert.That(str.Equals("_"), Is.True);
		}
 
		[Test]
		public void Encode64Url_Should_Replace_ThreeSlash_With_ThreeUnderscore()
		{
			var str = "///".EncodeBase64Url();
 
			Assert.That(str.Equals("___"), Is.True);
		}
 
		[Test]
		public void Decode64Url_Should_Replace_Underscore_With_Slash()
		{
			var str = "_".DecodeBase64Url();
 
			Assert.That(str.Equals("/"), Is.True);
		}
 
		[Test]
		public void Decode64Url_Should_Replace_ThreeUnderscore_With_ThreeSlash()
		{
			var str = "___".DecodeBase64Url();
 
			Assert.That(str.Equals("///"), Is.True);
		}
 
 
		[Test]
		public void Encode64Url_Should_Replace_Equal_With_Pipe()
		{
			var str = "=".EncodeBase64Url();
 
			Assert.That(str.Equals("|"), Is.True);
		}
 
		[Test]
		public void Encode64Url_Should_Replace_ThreeEqual_With_ThreePipe()
		{
			var str = "===".EncodeBase64Url();
 
			Assert.That(str.Equals("|||"), Is.True);
		}
 
 
		[Test]
		public void Decode64Url_Should_Replace_Pipe_With_Equal()
		{
			var str = "|".DecodeBase64Url();
 
			Assert.That(str.Equals("="), Is.True);
		}
 
		[Test]
		public void Decode64Url_Should_Replace_ThreePipe_With_ThreeEqual()
		{
			var str = "|||".DecodeBase64Url();
 
			Assert.That(str.Equals("==="), Is.True);
		}
 
 
		[Test]
		public void Encode64Url_Should_Replace_EqualSlashPlus_With_MinusUnderscorePipe()
		{
			var str = "=+/".EncodeBase64Url();
 
			Assert.That(str.Equals("|-_"), Is.True);
		}
 
 
		[Test]
		public void Decode64Url_Should_Replace_MinusUnderscorePipe_With_EqualSlashPlus()
		{
			var str = "|-_".DecodeBase64Url();
 
			Assert.That(str.Equals("=+/"), Is.True);
		}
 
 
		[Test]
		public void Encode64Url_Should_Replace_EqualSlashPlus_With_MinusUnderscorePipe_With_Alpha_Numeric_Characters()
		{
			var str = "1A=2b+3C/4d".EncodeBase64Url();
 
			Assert.That(str.Equals("1A|2b-3C_4d"), Is.True);
		}
 
 
		[Test]
		public void Decode64Url_Should_Replace_MinusUnderscorePipe_With_EqualSlashPlus_With_Alpha_Numeric_Characters()
		{
			var str = "1a|2B-3c_4D".DecodeBase64Url();
 
			Assert.That(str.Equals("1a=2B+3c/4D"), Is.True);
		}
 
 
 
		[Test]
		public void Encode64Url_Should_Return_Same_String_When_Empty()
		{
			var str = string.Empty.EncodeBase64Url();
 
			Assert.That(string.IsNullOrEmpty(str), Is.True);
		}
 
 
		[Test]
		public void Decode64Url_Should_Return_Same_String_When_Empty()
		{
			var str = string.Empty.DecodeBase64Url();
 
			Assert.That(string.IsNullOrEmpty(str), Is.True);
		}
 
 
		[Test]
		public void Encode64Url_Should_Return_Same_String_When_Null()
		{
			string str = null;
 
			str = str.EncodeBase64Url();
 
			Assert.That(string.IsNullOrEmpty(str), Is.True);
		}
 
 
		[Test]
		public void Decode64Url_Should_Return_Same_String_When_Null()
		{
			string str = null;
 
			str = str.DecodeBase64Url();
 
			Assert.That(string.IsNullOrEmpty(str), Is.True);
		}
 
 
	}

There are other ways of fixing this and one can read them at
http://blogs.iis.net/thomad/archive/2007/12/17/iis7-rejecting-urls-containing.aspx
http://bentaylor.org/dasBlog-Patch-Add-Choice-Of-Dash-For-Post-Title-URL-Spaces.aspx

Share

One Response

  1. nika1218 Says:

    Thanks! It was really helpful for me!

Leave a Comment