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
-
Gath Adams recommends Base64 encoding on any parameters that can contain slashes. He also explains the issue in more detail: Blog entry: gathadams.com/2009/01/06/…– TomalakCommented Feb 26, 2009 at 18:10
-
2You could also come up with some other way to mask the slash, say, replace it with something else by convention. I know. That's ugly as well, but at least the URL stays somewhat readable.– TomalakCommented Feb 26, 2009 at 20:10
-
2I noticed that forward slashes and dots give me errors. I made a quick helper that replaces them with "-slash-" and "-dot-". Wonder why the regular Url.Encode/Decode don't work something out. Also, why would an escaped character be giving any errors?– Boris CallensCommented Mar 23, 2009 at 8:06
-
2Whoa, there partner! Base64 encoding includes the slash character too! That's not a solution you can rely on for this problem.– Andrew ArnottCommented Nov 14, 2009 at 18:52
-
7This isn't an encoding issue with routing; it's apparently a bug in the .NET Uri class. According to [my reading of] the URI RFC, encoded slashes in the path should not be considered segment separators. MVC Routing doesn't have a chance to get it right because the Uri class (incorrectly) decodes the slashes before routing even sees it. See section 2.2 and 2.4 of the RFC. labs.apache.org/webarch/uri/rfc/rfc3986.html#reserved– Andrew ArnottCommented Nov 15, 2009 at 3:43
9 Answers 9
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
-
I am not comfortable with doing this as a general practice, especially on a public-facing website, but I did do this on an intranet webapp and don't feel too guilty about it. Thanks for pointing this solution out!– jkadeCommented Jun 19, 2012 at 19:46
-
7@jkade (or anyone) why are you not comfortable with this on a public facing website?– walCommented Sep 17, 2012 at 11:24
-
2For those who only want it for a single route, you can do the same via RouteAttribute to your controller's action, e.g. [Route("{*id}")]– VitalyCommented Jul 27, 2016 at 14:34
-
1
Here's a simple explanation of the solution and a summation of what has already been said.
Request side:
- UrlEncode your path.
- Replace the '%' with '!'.
- Make the request.
Response side:
- Replace the '!' with '%'.
- UrlDecode your path.
- Use the parameters as they were intended.
Rinse, repeat, enjoy.
-
1You may, like me, also run into this issue: Application Error: The length of the URL for this request exceeds the configured maxUrlLength value. It can be solved by adding this web.config value: <system.web> <httpRuntime maxUrlLength="1000" maxQueryStringLength="2048" /> Commented Mar 9, 2011 at 16:35
-
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.
-
This sounds great. I will use this as the answer once .NET 4.0 is released. Commented Nov 17, 2009 at 14:40
-
4This doesn't work. You get blue underlines in Visual Studio and it seems to have no effect.– cdmckayCommented Jun 22, 2011 at 1:40
-
12
-
1Years and years later, still an issue with the .NET Framework 4.7.1 and the Uri class. Tks a lot. This is a very obscure behavior for me. Note that for class libraries projects this problem does not occur. Commented Sep 14, 2018 at 13:17
-
@StephenLloyd this worked for me in the web.config (ASP.NET app using the .NET Framework classic 4.7.1). Commented Sep 14, 2018 at 13:33
One other option is to use a querystring value. Very lame, but simpler than custom encoding.
http://localhost:5000/Home/About?100%2f200
-
Good call, Jon. This is the only safe way I can come up with. It breaks convention a bit, but solves the problem when your ID has to be a string of any characters. Commented Jan 28, 2013 at 15:10
-
1I don't think this is lame - I think it's the best option - I think your example is wrong though? Should be - /About?x=100%2f200 - no??– niicoCommented Apr 13, 2017 at 9:00
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
You can avoid the double encoding/decoding suggestions above and simply use HttpServerUtility.UrlTokenEncode and the corresponding UrlTokenDecode.
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
})
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);
}
Just use Server.UrlDecode
. It will work, I've tested.
-
UrlDecoding is not the problem here, it is the routing within MVC and the fact that encoded strings with slashes (%2f) will be parsed in the routing as if they are (%2f) are part of the url.– RodiCommented Jan 22, 2014 at 10:36
Explore related questions
See similar questions with these tags.