Mathias F
Mathias F

Reputation: 15931

URL-encoded slash in URL

My Map is:

routes.MapRoute(
   "Default",                                             // Route name
   "{controller}/{action}/{id}",                          // URL with params
   new { controller = "Home", action = "Index", id = "" } // Param defaults
);

If I use the URL http://localhost:5000/Home/About/100%2f200 there is no matching route. I change the URL to http://localhost:5000/Home/About/100 then the route is matched again.

Is there any easy way to work with parameters that contain slashes? Other escaped values (space %20) seem to work.

EDIT:

To encode Base64 works for me. It makes the URL ugly, but that's OK for now.

public class UrlEncoder
{ 
    public string URLDecode(string  decode)
    {
        if (decode == null) return null;
        if (decode.StartsWith("="))
        {
            return FromBase64(decode.TrimStart('='));
        }
        else
        {
            return HttpUtility.UrlDecode( decode) ;
        }
    }

    public string UrlEncode(string encode)
    {
        if (encode == null) return null;
        string encoded = HttpUtility.PathEncode(encode);
        if (encoded.Replace("%20", "") == encode.Replace(" ", ""))
        {
            return encoded;
        }
        else
        {
            return "=" + ToBase64(encode);
        }
    }

    public string ToBase64(string encode)
    {
        Byte[] btByteArray = null;
        UTF8Encoding encoding = new UTF8Encoding();
        btByteArray = encoding.GetBytes(encode);
        string sResult = System.Convert.ToBase64String(btByteArray, 0, btByteArray.Length);
        sResult = sResult.Replace("+", "-").Replace("/", "_");
        return sResult;
    }

    public string FromBase64(string decode)
    {
        decode = decode.Replace("-", "+").Replace("_", "/");
        UTF8Encoding encoding = new UTF8Encoding();
        return encoding.GetString(Convert.FromBase64String(decode));
    }
}

EDIT1:

At the end it turned out that the best way was to save a nicely formated string for each item I need to select. Thats much better because now I only encode values and never decode them. All special characters become "-". A lot of my db-tables now have this additional column "URL". The data is pretty stable, thats why I can go this way. I can even check, if the data in "URL" is unique.

EDIT2:

Also watch out for space character. It looks ok on VS integrated webserver but is different on iis7 Properly url encode space character

Upvotes: 62

Views: 77739

Answers (9)

user11406534
user11406534

Reputation: 11

For inbound encoded '/' issue, I was able to fix my issue by adding '*' to catchall the id parameter and then was able to passing an encoded '/' into the the control correctly (the parameter was a string with an encoded '/')

routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{*id}",
            defaults: new 
            { 
                controller = "Control", 
                action = "Action", 
                id = UrlParameter.Optional 
            })

Upvotes: 1

silentnoise
silentnoise

Reputation: 9

You can avoid the double encoding/decoding suggestions above and simply use HttpServerUtility.UrlTokenEncode and the corresponding UrlTokenDecode.

Upvotes: 1

shijas km
shijas km

Reputation: 11

Just use Server.UrlDecode. It will work, I've tested.

Upvotes: -3

Don Rolling
Don Rolling

Reputation: 2339

Here's a simple explanation of the solution and a summation of what has already been said.

Request side:

  1. UrlEncode your path.
  2. Replace the '%' with '!'.
  3. Make the request.

Response side:

  1. Replace the '!' with '%'.
  2. UrlDecode your path.
  3. Use the parameters as they were intended.

Rinse, repeat, enjoy.

Upvotes: 26

simonox
simonox

Reputation: 559

Same for Java / Tomcat.

There is still a problem if you have got an encoded "/" (%2F) in your URL.

RFC 3986 - Section 2.2 says: "If data for a URI component would conflict with a reserved character's purpose as a delimiter, then the conflicting data must be percent-encoded before the URI is formed." (RFC 3986 - Section 2.2)

But there is an Issue with Tomcat:

http://tomcat.apache.org/security-6.html - Fixed in Apache Tomcat 6.0.10

important: Directory traversal CVE-2007-0450

Tomcat permits '\', '%2F' and '%5C' [...] .

The following Java system properties have been added to Tomcat to provide additional control of the handling of path delimiters in URLs (both options default to false):

  • org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: true|false
  • org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH: true|false

Due to the impossibility to guarantee that all URLs are handled by Tomcat as they are in proxy servers, Tomcat should always be secured as if no proxy restricting context access was used.

Affects: 6.0.0-6.0.9

So if you have got an URL with the %2F character, Tomcat returns: "400 Invalid URI: noSlash"

You can switch of the bugfix in the Tomcat startup script:

set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%   -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true 

Upvotes: 9

BillB
BillB

Reputation: 404

That's interesting about .NET 4. Anyway, this link describes RFC 1738 and includes which characters need encoding and which are just "unsafe". link text

If I want an SEO friendly URL, (like when you want to put a forum post subject in the URL), is skip encoding and replace anything that's not A-Z, a-z, 0-9.

public static string CreateSubjectSEO(string str)
    {
        int ci;
        char[] arr = str.ToCharArray();
        for (int i = 0; i < arr.Length; i++)
        {
            ci = Convert.ToInt32(arr[i]);
            if (!((ci > 47 && ci < 58) || (ci > 64 && ci < 91) || (ci > 96 && ci < 123)))
            {
                arr[i] = '-';
            }
        }
        return new string(arr);
    }

Upvotes: 0

Andrew Arnott
Andrew Arnott

Reputation: 81801

In .NET 4.0 beta 2, the CLR team has offered a workaround.

Add this to your web.config file:

<uri> 
    <schemeSettings>
        <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
    </schemeSettings>
</uri>

This causes the Uri class to behave according to the RFC describing URIs, allowing for slashes to be escaped in the path without being unescaped. The CLR team reports they deviate from the spec for security reasons, and setting this in your .config file basically makes you take ownership of the additional security considerations involved in not unescaping the slashes.

Upvotes: 24

Jon Galloway
Jon Galloway

Reputation: 53155

One other option is to use a querystring value. Very lame, but simpler than custom encoding.

http://localhost:5000/Home/About?100%2f200

Upvotes: 14

Mehrdad Afshari
Mehrdad Afshari

Reputation: 422172

If it's only your last parameter, you could do:

routes.MapRoute(
    "Default",                                                // Route name
    "{controller}/{action}/{*id}",                            // URL with parameters
    new { controller = "Home", action = "Index", id = "" });  // Parameter defaults

Upvotes: 49

Related Questions