2

I have a site running locally and on two other servers (serverA, serverB). I am running IIS 10 locally and IIS 8.5 on the other two servers.

Requests to Web Api 2 routes (defined through attribute routing) are handled correctly on my local site and on serverA but not on serverB.

I always get 404 responses from the server when making requests to the Web Api 2 routes but other pages serve correctly.

I have found that if I add folders to my site root that match the request url and add an index.html in the final folder the Web Api 2 route request is correctly handled and returns a valid response.

Example: Normally a request of GET domain.com/api/values returns 404 on serverB and a { value1: "1", value2: "2" } on serverA.

On serverB if my site is located at c:\site and I ensure c:\site\api\values\index.html exists (even if the index.html is empty) then GET domain.com/api/values will return { value1: "1", value2: "2" }.

I believe something is misconfigured with extensionless routing or request handlers on the one server but on comparing the web.config of the sites on the three servers I haven't figured out what the issue/difference is.

I have never seen this behavior before.

Here is my serverB web.config -> system.webServer section

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
      <remove name="XHtmlModule" />
      <add name="Glimpse" type="Glimpse.AspNet.HttpModule, Glimpse.AspNet" preCondition="integratedMode" />
    </modules>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="UrlRoutingHandler" />
      <remove name="WebDAV" />
      <remove name="ChartImageHandler" />
      <add name="ChartImageHandler" preCondition="integratedMode" verb="*" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      <add name="Glimpse" path="glimpse.axd" verb="GET" type="Glimpse.AspNet.HttpHandler, Glimpse.AspNet" preCondition="integratedMode" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,OPTIONS,DELETE" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,OPTIONS,DELETE" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,OPTIONS,DELETE" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
    </handlers>
</system.webServer>

What could be misconfigured that would prevent IIS from serving requests unless a file exists on the filesystem at that request path?

seangwright
  • 17,245
  • 6
  • 42
  • 54

1 Answers1

1

The problem was due to configuration changes in IIS at the server level to allow Let's Encrypt to work correctly.

My work is using Let's Encrypt to allow us to use a valid cert on internally used domain aliases for sites so we don't have to pay for certs.

The solution to a common issue with serving extensionless static files in the /.well-known/acme-challenge/ subdirectory of a site is to Move the StaticFile mapping above the ExtensionlessUrlHandler mappings.

It seems the problem is that when this is applied Static Files are handled before Extensionless Urls and IIS looks for a file without an extension at the Web Api route path and only serves the request for later modules if the earlier ones found what they were looking for.

I have not figured out how to get the requirements of Let's Encrypt on IIS and ExtensionlessUrlHandler to co-exist but I will update this answer if I do.

seangwright
  • 17,245
  • 6
  • 42
  • 54