Search code examples
asp.net-coreiiskestrel

asp.net core controller action route uses encoded slash to determine route (IIS only)


I have an asp.net core 2.2 mvc action method and GET it from the client JavaScript code :

[Route("/search/{searchterm}")]
public IActionResult Search(string searchterm)
{
    // code
}

Now, when I navigate to search with the searchstring abc/def the uri in the browser is /search/abc%2Fdef because the / gets encoded

I get a 404 though, because the routing attribute decoded the slash and the says /search/abc/def does not match my route. What I want is to treat the %2F as a normal piece of content so the searchstring is abc/def inside of my action method.

Funny(?) thing is, this does not happen on my local machine where I run from VS2017 (which runs Kestrel I guess) but only on the test server where it runs on IIS.

Is this an IIS thing? or maybe the loadbalancer is doing something?


Solution

  • You can use an asterisk to indicate that searchterm can contain slashes. This is called a catch-all parameter, and looks like this:

    [Route("/search/{**searchterm}")]
    public IActionResult Search(string searchterm)
    {
        // code
    }
    

    From the documentation:

    You can use an asterisk (*) or double asterisk (**) as a prefix to a route parameter to bind to the rest of the URI. These are called a catch-all parameters. For example, blog/{**slug} matches any URI that starts with /blog and has any value following it, which is assigned to the slug route value. Catch-all parameters can also match the empty string.

    The catch-all parameter escapes the appropriate characters when the route is used to generate a URL, including path separator (/) characters. For example, the route foo/{*path} with route values { path = "my/path" } generates foo/my%2Fpath. Note the escaped forward slash. To round-trip path separator characters, use the ** route parameter prefix. The route foo/{**path} with { path = "my/path" } generates foo/my/path.