Route parameter with slash "/" in URL

53,710

Solution 1

@bet.. I think the genericUriParserOptions is no longer applicable to .net 4.5 or later..

Also as suggested by @JotaBe, you might need to correctly decode the url request. In most case the %2F will be automatically translated to a slash '/'. So if you need to escape it you will need to decode the '%' char in the first place.. so your URL: will look something like: www.domain.com/api/orders/23%252F06%252F2015/customers

Notice the characters '%252F' will be translated to the actual '%2F'

EDIT

Ok here is the complete solution (Tried it and working for me):

  1. Assuming you have an API endpoint like so:

    [Route("orders/{date}/customers")]
    public HttpResponseMessage Get(string date)
    {
    }
    
  2. In the web.config you will need to set the requestPathInvalidCharacters to empty which tells the asp.net to allow all request

    <system.web>
        <httpRuntime targetFramework="4.5" requestPathInvalidCharacters=""/>                
    </system.web>
    <system.webServer>
        <security>
          <requestFiltering allowDoubleEscaping="true" />
        </security>
    </system.webServer>
    
  3. When the client sending the request to the API you will need to make sure to escape the '%' like so:

    www.domain.com/api/orders/23%252F06%252F2015/customers

  4. You then need to decode the request

    [Route("orders/{date}/customers")]
    public HttpResponseMessage Get(string date)
    {
            DateTime actualDate = DateTime.Parse(System.Net.WebUtility.UrlDecode(date)); // date is 23/06/2015
    }
    

Solution 2

As noted in the comment by @AlexeiLevenkov, this is wrong:

You cannot have a parameter in the URL which accepts forward slashes, because this is a special symbol which separates each URL fragment. So, whenever you include this symbol in your URL, there will be new fragments, and a single parameter can't include several fragments.

If you want more details, read this, but these are the most relevant excerpts:

  • the URL path finishes in the first ? or # found in the URL. So, the slashes only create fragments in the section of the URL path before the occurrence or one of those symbols.
  • From section 3.4: The query component is indicated by the first question mark ("?") character and terminated by a number sign ("#") character or by the end of the URI.

So, the query string can include forward slashes, /, if desired, and they will not define path segments at all.

These are some solutions for the question:

  • include fragments for day, month and year, like this: [Route("orders/{month}/{day}/{year}/customers")] and then create the date on the server side
  • require the user to use a different separator, like dash or dot, which won't create problems, receive it at string an parse it yourself (or use your own custom binder to support that format)
  • use the URL Rewrite extension to change the URL before it reaches the routing system, and parse it as explained in the previous solution (this requires hosting in IIS)
  • receive it as a query string, i.e. something like this: ´?date=02/03/2015´ (you'd better encode it)

NOTE: your original question said "query string", and my comment about encoding referred to the query string, which is the last segment of an URL after the question mark, if present, like &id=27. I corrected your question so that it doesn't mention "query string", which was not the right name for what you need

Solution 3

C# has its own method who skips the rules of escape sequences the name of method is Uri.UnescapeDataString(your querystring parameter) you can use it while getting the parameters value

Solution 4

You can use the following URI [Route("orders/{DD:int}/{MM:int}/{YY:int}}/customers")] and then use a custom model binder to take DD/MM/YY and turn them into a date that you can bind in your action method.

You can choose how you want to deal with constraints (go stricter with regex's) or use validation and return 400 if it doesn't match.

The simpler approach is, to take the Day/Month/Year and put it together in code.

Here is a link for dealing with modelbinding.

Share:
53,710

Related videos on Youtube

bet
Author by

bet

Updated on July 09, 2022

Comments

  • bet
    bet almost 2 years

    I know you can apply a wildcard in the route attribute to allow / such as date input for example:

    [Route("orders/{*orderdate}")]
    

    The problem with wildcard is only applicable to the last paramter in URI. How do I solve the issue if want to have the following URI:

    [Route("orders/{orderdate}/customers")]
    

    Update:

    I know there are few options to solve the issue by refactoring the code so please do not offer a solution something like:

    1. change the route template to [Route("orders/customers/{orderdate}")]
    2. change the date to a different format (e.g. "dd-mm-yyyy")
    • Josh Schultz
      Josh Schultz almost 8 years
      I appreciate this. I wasn't aware you could wildcard in the route, aka the * in {*orderdate}. This actually solved my problem, as my parameter was at the end of the URL.
  • bet
    bet almost 9 years
    tried that with '%2F' and no luck... giving me invalid request error
  • bet
    bet almost 9 years
    it is not about encoding it correctly ! '%2F' will automatically be treated as '/' when API receives the request
  • bet
    bet almost 9 years
    also tried to set the following setting in machine and web config but no luck.. <uri> <schemeSettings> <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" /> <add name="https" genericUriParserOptions="DontUnescapePathDotsAndSlashes" /> </schemeSettings> </uri>
  • Daniel
    Daniel almost 9 years
    I don't see how this answer the users question.
  • ronnie
    ronnie almost 9 years
    @Daniel.. if you know the better way to do it then post it here !! i have dealt with the same issue in the past and solved it using '%252F'
  • bet
    bet almost 9 years
    @ronnie - seems to be doing the job for me
  • Alexandre
    Alexandre over 7 years
    perfect !! " requestPathInvalidCharacters="" " was missing in my web.config
  • Alexei Levenkov
    Alexei Levenkov almost 7 years
    It is ok to have / in path (as percent encoded %2f) and in query parameters (as is or encoded) -tools.ietf.org/html/rfc3986#section-3.3. So most of the answer is flat out wrong, but suggested solutions are ok as workarounds (-1 for first half, +1 for second =0)
  • JotaBe
    JotaBe almost 7 years
    @AlexeiLevenkov Good point. I've corrected my answer to reflect that big mistake.
  • Rudey
    Rudey over 6 years
    Double escaping shouldn't be necessary.
  • stomy
    stomy over 5 years
    Why is the requestPathInvalidCharacters="" necessary?
  • KainWhite
    KainWhite over 2 years
    @stomy Because we escaped % symbol in url, so when API decodes the string it sees this % symbol in it and by default % symbol is an invalid symbol in url (sauce)