Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API + jQuery AJAX DELETE request returning 404

My ASP.NET WebAPI & MVC application is returning a 404 error when I request a PUT or DELETE. It used to be returning a 405, but I resolved that by enabling CORS. I have tried all sorts of different solutions (disabling WebDAV, change routes, put querystring in request), but none seem to have worked for me. I'm hoping I just missed something extremely simple. Here's relevant simplified code from each relevant file in my application:

jQuery AJAX request:

$.ajax({
    url: "api/Signout?id=3",
    type: "DELETE",
    crossDomain: true,
});

SignoutController (GET and POST methods work from here just fine):

public void Delete([FromUri] int id)
{
    //Do things
}

WebApiConfig routes:

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

//For another part of the application
config.Routes.MapHttpRoute(
    name: "SaveSignout",
    routeTemplate: "api/{controller}/{signout}"
);

Web.config:

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <clear />
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
      <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
    </customHeaders>
  </httpProtocol>
  <modules>
    <remove name="FormsAuthenticationModule" />
    <remove name="WebDAVModule"/>
  </modules>
  <handlers>
    <remove name="WebDAV" />
    <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
    <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" />
  </handlers>
</system.webServer>

RouteConfig.cs (saw this somewhere else on SO)

routes.IgnoreRoute("{*x}", new { x = @".*\.asmx(/.*)?" }); 

Fiddler DELETE request (simplified referer):

DELETE /api/Signout?id=45 HTTP/1.1
Host: localhost:51301
Connection: keep-alive
Cache-Control: no-cache
Authorization: Negotiate (large base64 here)
Pragma: no-cache
Accept: */*
Origin: http://localhost:51301
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36
Referer: http://localhost:51301/Home/Controller/Id
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8

Fiddler response:

HTTP/1.1 404 Not Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/8.0
X-SourceFiles: =?UTF-8?B? (base64 of full local path to api/Signout)
Persistent-Auth: true
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
WWW-Authenticate: Negotiate oRswGaADCgEAoxIEEAEAAABDh+CIwTbjqQAAAAA=
Date: Tue, 17 Feb 2015 18:05:18 GMT
Content-Length: 4966

It's just a slew of various "solutions" I've come across that all apparently worked for those involved. Where am I going wrong?

like image 517
Scott Avatar asked Feb 17 '15 18:02

Scott


2 Answers

By default IIS does not serve DELETE requests: the system.webServer handlers defined in Web.Config can set how to process requests when your website's Application Pool has a "Managed pipeline mode" of Integrated (IIS7) or Classic (ISAPI 32 & 64 bit flavours). In your example, only ISAPI 64 bit is controlled. The following shows the other variations.

<system.webServer>
    <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,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>

Reference:

  • Related Answer on SO
  • Extensionless URL Handler Background on MSDN Blog
  • Background on Classic/ISAPI vs Integrated on SO
like image 168
richaux Avatar answered Sep 20 '22 05:09

richaux


Richaux is correct, IIS does not serve DELETE, PUT and other requests by default. However, the Web.config part in that answer is showing how it was done in the MVC4 template. When creating a MVC5 Web API project from the MVC5 template you'll see the relevant part that registers the handler for all verbs:

<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>
like image 37
huysentruitw Avatar answered Sep 19 '22 05:09

huysentruitw