11

With the default web api route

config.Routes.MapHttpRoute(
            name: "API Default",
            routeTemplate: "api/{controller}/{id}",
            defaults: new
                      {
                          id = RouteParameter.Optional
                      }
            );

and a controller

public class TestController : ApiController
{
    [HttpGet]
    public HttpResponseMessage Get(string id)
    {
        return Request.CreateResponse(HttpStatusCode.OK, id);
    }
}

A request to 'api/test/1'

returns 1

If for some reason you send a request to 'api/test/1%20'

the route 404's.

Now this example may seem silly since browsers trim trailing spaces, but

for a route like 'api/{controller}/{id}/{extrastuff}'

the space in '1 ' would convert to '1%20' and the request will 404 on the route not being found.

Steve
  • 25,806
  • 2
  • 33
  • 43

2 Answers2

37

Your issue has nothing to do with WebAPI itself but how Asp.Net handles some specific urls. And Asp.Net handles these urls in a very paranoid way, so you need to tell it to relax.

Add this line to your web.config under system.web:

<httpRuntime relaxedUrlToFileSystemMapping="true" />

You can read more about this topic:

Also on SO:

Community
  • 1
  • 1
nemesv
  • 138,284
  • 16
  • 416
  • 359
  • seems silly that a routing mvc engine would have this set to false by default when a huge advantage of mvc is to not have the url be related to the file system. – Steve Nov 15 '12 at 22:02
  • 1
    It's not the routing engines decision, it's ASP.NET at the very core protecting everything built on top of it. So beware if you change this that you're relaxing the rules for everything under your application at that point. – Drew Marsh Nov 16 '12 at 04:50
  • 1
    This just crashes the app as soon as I add it – Dan Jun 05 '15 at 11:38
  • 1
    This fixed helped but I am still getting some issues. For a webapi endpoint that takes a string username, we are getting the following results: Cases that work: abcd-. abcd@. abcd. abcd@ Cases that doesn't work: abcd.- abcd.-@ abcd-. abcd.@ abcd-@. – Dan Csharpster Oct 01 '15 at 17:21
  • Thanks, it worked perfect for me. No code change needed, what a blessing. – Mark Apr 24 '18 at 13:57
  • This solution still works? In my case doesn't works. My .NET version is 4.6.1 – erikscandola Jan 30 '19 at 08:57
  • 1
    your comment still helps ppl to solve the same issue – Basil Jul 19 '21 at 00:20
2

Add this to handlers

      <add name="ExtensionlessUrlHandler-Integrated-4.0-ForApi"
     path="api/*"
     verb="*"
     type="System.Web.Handlers.TransferRequestHandler"
     preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
Toolkit
  • 10,779
  • 8
  • 59
  • 68
  • This worked like a charm. My problem was that I needed to download a file passing the filename as the last part of a URL. `https://mywebsite/api/download/getfile/{filename}` – Luca Natali Nov 12 '18 at 11:12