4

I am using WebAPI PUT and DELETE methods to perform actions from my website via AJAX using jQuery. My server is Windows Server 2008 R2 with Plesk installed. POST and GET requests work just fine, but PUT and DELETE fail.

I was originally getting a 401 Unauthorized response when I first deployed my site to the server. I then performed some actions and it turned into 405 Method not allowed.

I am now at a point where I'm receiving an Internal Server error:

Handler “ExtensionlessUrlHandler-Integrated-4.0” has a bad module “ManagedPipelineHandler” in its module list

Now, there are lots of posts about this, and sadly I can't get it to work yet.

Here's what I've tried:

  • Added remove tags within web.config for WebDAV handler and module
  • Set permissions to execute scripts and executables within Handler Mappings
  • Adding the PUT and POST verbs to within IIS
  • Added PUT and POST verbs to the web.config
  • Downloading the .NET Framework and performing a 'repair'
  • Re-registered .NET Framework as shown in this answer
  • Investigated CORS but I'm not doing any cross site scripting, It's just AJAX called from the same domain

How can I get rid of this message and allow my PUT and DELETE to work?

Heres my web.config

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  <sectionGroup name="elmah">
      <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
      <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
      <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
      <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
    </sectionGroup></configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />
    </providers>
  </entityFramework>
  <connectionStrings></connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="owin:AppStartup" value="uQuiz.OwinStart" />
    <add key="elmah.mvc.disableHandler" value="false" />
    <add key="elmah.mvc.disableHandleErrorFilter" value="false" />
    <add key="elmah.mvc.requiresAuthentication" value="false" />
    <add key="elmah.mvc.IgnoreDefaultRoute" value="false" />
    <add key="elmah.mvc.allowedRoles" value="*" />
    <add key="elmah.mvc.allowedUsers" value="*" />
    <add key="elmah.mvc.route" value="elmah" />
  </appSettings>
  <system.web>
    <compilation targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      <add namespace="Westwind.Utilities" /><add namespace="Westwind.Web" /></namespaces>
    </pages>
    <httpModules>
      <add name="ScriptCompressionModule" type="Westwind.Web.ScriptCompressionModule,Westwind.Web" />
      <add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web" />
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" /><add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
    </httpModules>
    <sessionState mode="StateServer" cookieless="false" timeout="60" stateConnectionString="tcpip=loopback:42424" stateNetworkTimeout="3600" />
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers accessPolicy="Read, Execute, Script">
      <!-- Remove WebDAV modules to make PUT methods on WebAPI work -->
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Execute" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
      <add name="ScriptCompressionModule" type="Westwind.Web.ScriptCompressionModule,Westwind.Web" />
      <add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web" /><add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" /><add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" /><add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
    </modules>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.0.0" newVersion="5.2.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.0.0" newVersion="5.2.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Ninject" publicKeyToken="c7192dc5380945e7" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Ninject.Web.Common" publicKeyToken="c7192dc5380945e7" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Http.WebHost" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.0.0" newVersion="5.2.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.22.0" newVersion="4.2.22.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.AspNet.SignalR.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.1.2.0" newVersion="2.1.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="MySql.Data" publicKeyToken="c5687fc88969c44d" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.8.3.0" newVersion="6.8.3.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <elmah>
  </elmah>
</configuration>
Community
  • 1
  • 1
Luke
  • 22,826
  • 31
  • 110
  • 193
  • I suggest you create a new WebAPI project and compare the web.config. This should just work out the box. – Ashley Medway Feb 18 '15 at 08:33
  • I'll post my web.config.. 1 sec :) – Luke Feb 18 '15 at 08:34
  • What's your parameter named on your PUT/DELETE methods? I ran into this when I tried to call the parameter that I was passing into a delete method 'propertyId' instead of 'id' as the framework expects – RSid Apr 03 '15 at 18:22
  • You should change the name of the parameter within your code to `propertyId` if you want it to accept that parameter, it should work. This question is specific to the PUT and DELETE verbs being rejected. – Luke Apr 04 '15 at 07:42

3 Answers3

1

An extract from my web.config around the ExtensionlessUrlHandler-Integrated-4.0.

Looking at the difference between yours and mine I don't have this section resourceType="Unspecified" requireAccess="Execute". I also use verb="*" that shouldn't make a difference but might be worth a try.

Also note I do not have accessPolicy="Read, Execute, Script" attribute in the handlers section. I also do not remove WebDAV.

<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>

Possible answer from: https://stackoverflow.com/a/18458139/1398425

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE" />
      <add name="Access-Control-Allow-Headers" value="Content-Type" />
    </customHeaders>
  </httpProtocol>
  <modules runAllManagedModulesForAllRequests="false">
    <remove name="WebDAVModule" />
  </modules>

  <validation validateIntegratedModeConfiguration="false" />
  <handlers>
    <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
    <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
    <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
    <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  </handlers>
</system.webServer>
Community
  • 1
  • 1
Ashley Medway
  • 7,151
  • 7
  • 49
  • 71
  • Thanks for this. I think that my section looked identical to yours until I started messing with it to try to get this to work. I'll try resetting it back to the original like yours and see if that does the trick. – Luke Feb 18 '15 at 08:43
  • Removing the WebDAV took the error message from `401` to `405`. – Luke Feb 18 '15 at 08:44
  • @Coulton Check the extract I added from answer: http://stackoverflow.com/a/18458139/1398425 – Ashley Medway Feb 18 '15 at 08:51
  • You might not want the CORS to be enabled in the custom headers mind, depends on how you need to use your api. I think the additional handlers maybe the fix for you. – Ashley Medway Feb 18 '15 at 08:52
  • Thanks, my only concern is that it will open my server up to attack? Shouldn't this work without having to allow all domains to access my WebAPI? – Luke Feb 18 '15 at 08:53
  • Ok, I'll add all the other stuff apart from the CORS and see what happens :) – Luke Feb 18 '15 at 08:53
  • It depends on how you access the WebAPI, You might just want to allow one site `` would allow example.com to make calls to your WebAPI – Ashley Medway Feb 18 '15 at 08:53
  • Sadly after making it match the web.config in that answer has just lead me back to the same error 'Internal Server Error - Bad module 'ManagedPipelineHandler'. I noticed that once I removed the `remove` for WebDAV it said that WebDAV has a bad module, so I added the remove tag back again. I just completely uninstalled and reinstalled .NET 4.5 and that didn't work either. – Luke Feb 18 '15 at 09:31
  • 1
    omg it's working!!!!!!! I disabled WebDAV for my application pool within IIS and it worked! I followed the instructions here http://www.exactsoftware.com/Docs/DocView.aspx?DocumentID=%7Bc288fa96-2eea-414f-843f-29a2a1531405%7D – Luke Feb 18 '15 at 10:18
  • Thank you so much for your help though, it's really appreciated! – Luke Feb 18 '15 at 10:21
  • The exactsoftware link provided by @Luke is no longer valid; it returns an Access Denied page. – David Keaveny Sep 24 '18 at 06:09
1

Actually removing WebDAV from my server caused the application to return a 503 Service Unavailable Error message, so I re-installed it.

I was able to fix this by disabling WebDAV for the individual application pool, this stopped the 'bad module' error.

Disable WebDAV for Individual App Pool:

  1. Click the affected web site in IIS
  2. Find WebDAV Authoring Tools in the list
  3. Click to open it
  4. Click Disable WebDAV in the top right.

Ta daaaa!

This link is where I found the instructions but it's not very clear.

Luke
  • 22,826
  • 31
  • 110
  • 193
1

For myself it wasn't enough to do everything @Luke was doing. I had to also go into my Programs and Features and and under Internet Information Services > World Wide Web Services > Common HTTP Features turn off WebDAV Publishing

That then fixed it for me.