Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Web API tries to serve physical directories instead of mapped controllers

I have an existing ASP.NET Web API 2 project that was previously served under route prefix /api/ (example.com/api/Users), but now it needs to be moved directly under the root (example.com/Users).

The problem is that now some of the routes match physical directories in the project root, and IIS tries to serve those directories when making such conflicting request.

This is what the project structure looks like:

MyApi/
  App_Start/
  Controllers/
  Models/
  ...
  Permissions/
  ...
  Global.asax
  Global.asax.cs
  ...
  Web.config

The routes are mapped using attribute routes: config.MapHttpAttributeRoutes();

And here's a simplified sample of a problematic controller:

namespace MyApi.Controllers
{
    [RoutePrefix("Permissions")]
    public class PermissionController
    {
        [Route("")]
        [HttpGet]
        [ResponseType(typeof(IEnumerable<Permission>))]
        public IHttpActionResult Get()
        {
            return ...

When a request is made to example.com/Permissions, IIS first responds with a 301 redirect to example.com/Permissions/ (trailing slash) and then with:

IIS 10.0 Detailed Error
HTTP Error 403.14 - Forbidden
The Web server is configured to not list the contents of this directory.

Detailed Error Information:
Module           DirectoryListingModule
Notification     ExecuteRequestHandler
Handler          StaticFile
Error Code       0x00000000

All other controllers without conflicting directory names work as expected.

I've tried both enabling and disabling runAllManagedModulesForAllRequests, I've tried adding and removing handlers like this:

<add name="ApiURIs-ISAPI-Integrated-4.0" path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" preCondition="integratedMode,runtimeVersionv4.0" />

And I've even tried removing the StaticFile handler, but nothing I've tried so far has worked.

This is the Web.config currectly. It is identical to what Visual Studio 2015 generates by default when creating a new empty Web API 2 project:

...
  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
      <remove name="OPTIONSVerbHandler"/>
      <remove name="TRACEVerbHandler"/>
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
    </handlers>
  </system.webServer>
...

So can I prevent IIS from trying to serve physical files inside the project? The API should only serve dynamically generated content from the controllers.

like image 442
Jarru Avatar asked Oct 23 '25 14:10

Jarru


1 Answers

After a lot of trial and error, I seem to have found the solution.

This flag makes the API prefer the controller instead of the directory:

System.Web.Routing.RouteTable.Routes.RouteExistingFiles = true;

Changes for Web.config:

  • runAllManagedModulesForAllRequests allows dots in the URL (/Users/firstname.lastmane)
  • Removing the StaticFile handler will return 404 errors instead of 403 erros for physical directories which don't match any mapped routes.

Content:

...
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <remove name="StaticFile" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
...
like image 159
Jarru Avatar answered Oct 26 '25 04:10

Jarru



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!