IIS7.5 Gives 500 Internal Server Error when trying to use DELETE verb

I found the answer here:

ASP.NET Core with IIS - HTTP Verb Not Allowed

This is the web.config

<configuration>
<!-- To customize the asp.net core module uncomment and edit the following section. 
     For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->
<system.webServer>
    <modules>
        <remove name="WebDAVModule" />
    </modules>
    <handlers>
        <remove name="aspNetCore" />
        <remove name="WebDAV" />
        <!-- I removed the following handlers too, but these
             can probably be ignored for most installations -->
        <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
        <remove name="OPTIONSVerbHandler" />
        <remove name="TRACEVerbHandler" />

        <add name="aspNetCore" 
             path="*" 
             verb="*" 
             modules="AspNetCoreModule" 
             resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="%LAUNCHER_PATH%" 
                arguments="%LAUNCHER_ARGS%" 
                stdoutLogEnabled="false"
                stdoutLogFile=".\logs\stdout" />
</system.webServer>


I found that removing webDav references from handlers and modules in the above solution still resulted in IIS 7.5, IIS 7 Windows server 2008 r2 (I never tested IIS 8) for http methods PUT, DELETE

HTTP Error 500.21 - Internal Server Error Handler "ExtensionlessUrlHandler-Integrated-4.0" has a bad module "ManagedPipelineHandler"

This server error is misleading and also given for improper .net installations where a handler is missing, and can be fixed by re-installing .Net, but that's probably not a solution, if it only affects PUT or DELETE requests to the extension-less route handler (GET, POST, and OPTIONS were fine). I read so many posts about enabling put and delete methods in MVC and Web api that seemed to claim this was a fix so I tried it anyway several times, restarted IIS etc, no change in the error.

the problem did not no go away until I added runManagedModulesForWebDavRequests="true" attribute to the modules element.

< modules runAllManagedModulesForAllRequests="true" runManagedModulesForWebDavRequests="true" >

http://www.iis.net/configreference/system.webserver/modules

By default runManagedModulesForWebDavRequests ="false" which means any webDav request is routed to WebDav. So far as I can deduce, A webdav request is all http PUT or DELETE requests as far as IIS is concerned, even if you have removed the webdav handler from web config and your request body doesn't conform to a webdav request. It's possible that uninstalling webDav might also correct the problem, but I never tried that; I have other sites running on the same server that depend on it.


The answer turns out to be caused by more of Microsoft's Broken by default policy.

Rather than acting as a web-server, accepting requests and handling them, ASP.net by default decides to ignore the majority of requests - because it thinks the user shouldn't be doing them.

The solution is to rip everything related to ASP.net out of IIS, and then re-add it correctly:

web.config

<?xml version="1.0"?>
<configuration>
    <modules runAllManagedModulesForAllRequests="true">
      <!--IISFIX: Whatever this is, it causes 405 Method Not Allowed errors on IIS when using PUT. (Microsoft's broken by defult)-->
      <remove name="WebDAVModule"/>
    </modules>
    <handlers>
         <!--IISFIX: ASP.net is broken by default. By default they will not accept verbs from the client.
         First we have to rip out everything related to ASP.net-->
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"/>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit"/>
      <remove name="SimpleHandlerFactory-ISAPI-2.0-64"/>
      <remove name="SimpleHandlerFactory-ISAPI-2.0"/>
      <remove name="SimpleHandlerFactory-Integrated"/>
      <remove name="SimpleHandlerFactory-Integrated-4.0"/>
      <remove name="SimpleHandlerFactory-ISAPI-4.0_64bit"/>
      <remove name="SimpleHandlerFactory-ISAPI-4.0_32bit"/>
         <!-- IISFIX: Now that we're ripped out everything related to ASP.net, put them back correctly.-->
      <add name="SimpleHandlerFactory-ISAPI-4.0_32bit" path="*.ashx" verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0"/>
      <add name="SimpleHandlerFactory-ISAPI-4.0_64bit" path="*.ashx" verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0"/>
      <add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0"/>
      <add name="SimpleHandlerFactory-Integrated" path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode"/>
      <add name="SimpleHandlerFactory-ISAPI-2.0" path="*.ashx" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0"/>
      <add name="SimpleHandlerFactory-ISAPI-2.0-64" path="*.ashx" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0"/>
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\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="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0"/>
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0"/>

      <!--IISFIX: WebDAV is also buggy, and interferes with client requests-->
      <remove name="WebDAV"/>

    </handlers>
  </system.webServer>
</configuration>

The problem now is that the web-site will not work on anyone else's machine; there are now hard-coded paths to files in web.config.

Why, oh why, couldn't Microsoft just do things right.

For completeness

For my own reference, here are the other things that i need to add to web.config every time because the defaults are wrong:

  <system.web>
    <httpRuntime/>
    <!-- IISFIX: By default IIS hides errors-->
    <customErrors mode="Off"/>
    <!-- IISFIX: By default IIS ignores the browser's culture -->
    <globalization culture="auto" uiCulture="auto"/>
  </system.web>

  <!-- ASP.net web-sites do not support WebPageTraceListener (only ASP.net web-applications) 
  So this section doesn't work; and does nothing. 
  But if Microsoft ever fixes IIS, we will start working automagically. -->
  <system.diagnostics>
    <trace>
      <listeners>
        <add name="WebPageTraceListener" type="System.Web.WebPageTraceListener, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
      </listeners>
    </trace>
  </system.diagnostics>

  <system.webServer>
    <!-- IISFIX: By default IIS ignores custom error pages -->
    <httpErrors existingResponse="PassThrough"/>
  </system.webServer>