HttpUtility.UrlEncode and Application_Start
As per http://ayende.com/blog/4599/hunt-the-bug, I've run into one of those scenarios whereby "Response is not available in t开发者_运维问答his context".
Greatly simplified, the following throws an exception in certain scenarios on Windows Server 2008/IIS7/ASP.NET 4.0
public class Global : HttpApplication
{
public void Application_Start(object sender, EventArgs e)
{
HttpUtility.UrlEncode("Error inside!");
}
}
The solutions that I've seen involve one of the following:
- Do as Ayende did and "write my own HttpUtility (well, take the one from Mono and modify it) to avoid this bug."
- or determine whether using HttpEncoder.Default instead does the trick. I'm trying to track down how best to do this.
- or use Uri.EscapeDataString as per Server.UrlEncode vs. HttpUtility.UrlEncode
Maybe it's not my best googling day, but how to implement HttpEncoder.Default?
Recommendations?
You can try this for encoding
public static string UrlEncode(string s)
{
return typeof(System.Net.WebClient).InvokeMember("UrlEncode", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new[] { "[#encoded] <data>" }) as string;
}
// by @DmitryDzygin
public static string UrlDecode(string s)
{
return typeof(System.Net.WebClient).Assembly.GetType("System.Net.HttpListenerRequest+Helpers").InvokeMember("UrlDecodeStringFromStringInternal", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { s, Encoding.UTF8 }) as string;
}
And if you don't feel comfortable with or your application is not running in FULL trust level, try this
public class HttpUtils : System.Web.Util.HttpEncoder
{
private static HttpUtils _encoder;
internal static HttpUtils Encoder
{
get { return _encoder ?? (_encoder = new HttpUtils()); }
}
internal string InternalUrlEncode(string s)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(s);
var encodedBytes = base.UrlEncode(bytes, 0, bytes.Length);
return System.Text.Encoding.UTF8.GetString(encodedBytes);
}
public static string UrlEncode(string s)
{
return Encoder.InternalUrlEncode(s);
}
}
I Know it is not still the best way but what could the best way be if we don't use HttpUtility.UrlEncode!..
Requires FULL trust
public static class DefaultHttpEncoder
{
public static string UrlEncode(string urlPart)
{
using (new NoHttpContext())
{
return HttpUtility.UrlEncode(urlPart);
}
}
public static string UrlDecode(string urlPart)
{
using (new NoHttpContext())
{
return HttpUtility.UrlDecode(urlPart);
}
}
private class NoHttpContext : IDisposable
{
private readonly HttpContext _context;
public NoHttpContext()
{
_context = HttpContext.Current;
HttpContext.Current = null;
}
public void Dispose()
{
HttpContext.Current = _context;
}
}
}
精彩评论