I need to request the following URL inside my application:
http://feedbooks.com/type/Crime%2FMystery/books/top
When I run the following code:
Uri myUri = new Uri("http://feedbooks.com/type/Crime%2FMystery/books/top");
The Uri
constructor decodes the %2F
into a literal /
, and I get a 404 error because it has changed the URL to:
http://feedbooks.com/type/Crime/Mystery/books/top
The Uri
class has a constructor that takes a parameter dontEscape
, but that constructor is deprecated and setting it to true
has no effect.
My first thought was to do something like:
Uri myUri = new Uri("http://feedbooks.com/type/Crime%252FMystery/books/top");
With the hopes that it would convert %25
into a literal %
, but that didn't work either.
Any ideas how to create a correct Uri
object for this particular URL in .NET?
It's a bit easier in .NET 4.0. You can put a setting in your config file like this:
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
It only works for the 'http' and 'https' schemes.
Or here's a new version of the LeaveDotsAndSlashesEscaped method. It doesn't need a particular Uri instance, just call it when your application starts up:
private void LeaveDotsAndSlashesEscaped()
{
var getSyntaxMethod =
typeof (UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic);
if (getSyntaxMethod == null)
{
throw new MissingMethodException("UriParser", "GetSyntax");
}
var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" });
var setUpdatableFlagsMethod =
uriParser.GetType().GetMethod("SetUpdatableFlags", BindingFlags.Instance | BindingFlags.NonPublic);
if (setUpdatableFlagsMethod == null)
{
throw new MissingMethodException("UriParser", "SetUpdatableFlags");
}
setUpdatableFlagsMethod.Invoke(uriParser, new object[] {0});
}
I ran into the same problem using 2.0...
I discovered a workaround posted at this blog:
// System.UriSyntaxFlags is internal, so let's duplicate the flag privately
private const int UnEscapeDotsAndSlashes = 0x2000000;
public static void LeaveDotsAndSlashesEscaped(Uri uri)
{
if (uri == null)
{
throw new ArgumentNullException("uri");
}
FieldInfo fieldInfo = uri.GetType().GetField("m_Syntax", BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo == null)
{
throw new MissingFieldException("'m_Syntax' field not found");
}
object uriParser = fieldInfo.GetValue(uri);
fieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo == null)
{
throw new MissingFieldException("'m_Flags' field not found");
}
object uriSyntaxFlags = fieldInfo.GetValue(uriParser);
// Clear the flag that we don't want
uriSyntaxFlags = (int)uriSyntaxFlags & ~UnEscapeDotsAndSlashes;
fieldInfo.SetValue(uriParser, uriSyntaxFlags);
}
It works perfectly.
Hope this helps (better late than never!)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With