10

I know this is a commonly addressed issue, and I've done everything that many posts here on SO suggest. When I try to delete a record using WebAPI (version 2) from my MVC5 front end running under local IIS, I get a 404 Not Found response. Here are the things I've tried:

I've added the following under <system.webServer /> in my WebAPI web.config:

<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
    </modules>
    <handlers>
      <remove name="WebDAV" />
      <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>

I've followed the instructions at: http://geekswithblogs.net/michelotti/archive/2011/05/28/resolve-404-in-iis-express-for-put-and-delete-verbs.aspx, which basically say to modify the ExtensionlessUrlHandler-Integrated-4.0 in IIS "Handler Mappings". It says to double click on the handler, click "Request Restrictions", and "Allow PUT and DELETE verbs". I've done this, and I still get the 404 error.

I've done an IIS reset.

Here's my MVC5 front end code that calls the WebAPI delete method - please note that when I manually navigate to api/bulletinboard/get/{0} where {0} is an integer, I get a valid JSON response. Below, contactUri is http://localhost/SiteName/api/bulletinboard/get/53 which returns valid JSON:

[HttpPost, ActionName("Delete")]
        public ActionResult Delete(string appId, int id)
        {
            response = client.GetAsync(string.Format("api/bulletinboard/get/{0}", id)).Result;
            contactUri = response.RequestMessage.RequestUri;
            response = client.DeleteAsync(contactUri).Result;

            if (response.IsSuccessStatusCode)
            {
                return RedirectToAction("MessageList", new { appId = appId });
            }
            else
            {
                LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
                    "Cannot delete message due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
                return View("Problem");
            }
        }

Here's my WebAPI delete method:

[HttpDelete]
        public HttpResponseMessage Delete(int id)
        {
            BulletinBoard bulletinBoard = db.BulletinBoards.Find(id);
            if (bulletinBoard == null)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }

            db.BulletinBoards.Remove(bulletinBoard);

            try
            {
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
            }

            return Request.CreateResponse(HttpStatusCode.OK, bulletinBoard);
        }

Here's my WebApiConfig.cs in my WebAPI project:

public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            config.EnableCors();

            // Web API routes
            config.MapHttpAttributeRoutes();

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

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

            var json = config.Formatters.JsonFormatter;
            json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
            config.Formatters.Remove(config.Formatters.XmlFormatter);

            config.Formatters.Add(new PlainTextFormatter());
        }

QUESTION: What else can I try to resolve this error? This works fine when deployed from my local environment to my company's development servers.

Mike Marks
  • 10,017
  • 17
  • 69
  • 128
  • your request url is `api/bulletinboard/get/{0}` whereas you are trying to reach the delete action...shouldn't it be `api/bulletinboard/delete/{0}`? – Kiran Jan 15 '14 at 15:19
  • @KiranChalla No, it should be how I have it. The `DeleteAsync` gets the result of the GET request and deletes it. I have this working as is in another project. I did however change it to what you suggested just to see what would happen, and I had the same 404 error. I think there's something about the DELETE request that IIS doesn't like... – Mike Marks Jan 15 '14 at 15:21
  • @KiranChalla Ah, it's a very strange situation... take a look at my answer below. – Mike Marks Jan 15 '14 at 15:42

9 Answers9

17

for those who still looking for enable DELETE & PUT The below code solve my problem

<validation validateIntegratedModeConfiguration="false" />
<handlers>
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />

  <!--This will enable all Web API verbose-->
  <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>
nabukhas
  • 193
  • 1
  • 9
  • 1
    I only needed the headers added to the WebAPI web.config to fix my scenario. My config didn't need the validation portion. – InquisitionX Oct 10 '17 at 18:49
  • In my case adding all the lines returned duplication error. So, I only added/enabled what was created by default, which was: Also note the scenario my be Classic or Integrated, depending on how your IIS is set up – Hannington Mambo Jan 08 '21 at 22:12
10

I've followed the instructions at: https://forums.asp.net/t/1961593.aspx?DELETE+PUT+verbs+result+in+404+Not+Found+in+WebAPI+only+when+running+locally

That says to only change this piece of code in your Web.config, and works fine for me!

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /> 
      </customHeaders>
    </httpProtocol>
    <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,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer>
8

If you are using IIS, make sure you have the HTTP Verb set to allowed in Request Filtering. If its not there, you can set it to allow it on the side.

enter image description here

Kalel Wade
  • 7,742
  • 3
  • 39
  • 55
5

We were struggling with DELETE/PUT returning 404 errors on IIS 8. We did all of the above answers changing web.config to accept all Verbs, enabling put/delete in the request filtering. We had also disabled webDAV multiple ways. We found that the application pool was set to classic verses integrated (what it should have been). Now DELETE/PUT verbs work fine.

Mark Jensen
  • 108
  • 1
  • 8
2

Mark Jensen solution worked for me.

Just changed my Application Pool from "Classic" to "Integrated" and my requests worked.

2

This issue can be fixed by IIS level configuration- Open IIS->select your website->IIS (section) ->Request Filtering ->HHTP Verbs

Remove DELETE verb/ OR allow DELETE verb

Issue will get resolved.

Yogesh Patil
  • 151
  • 1
  • 6
1

What I did was just switch from using local IIS to IIS Express via the project properties on my WebAPI project, as a workaround. Doing this and deleting a record then resulted in a 405 Method Not Allowed error. I then changed the lines of code:

response = client.GetAsync(string.Format("api/bulletinboard/get/{0}", id)).Result;
contactUri = response.RequestMessage.RequestUri;
response = client.DeleteAsync(contactUri).Result;

To:

response = client.DeleteAsync(string.Format("api/bulletinboard/delete/{0}", id)).Result;

This is very strange because I have another project that runs the first block of code and it deletes records just fine. Anyways, this resolved my local problem. I understand this doesn't really resolve my main issue which was using local IIS, but this workaround worked for me.

Mike Marks
  • 10,017
  • 17
  • 69
  • 128
0

If your project is working under IIS and not under IISExpress, try to set IISExpress Managed Pipeline Mode to Integrated. PUT and DELETE verbs seems to have problem under Classic Managed Pipeline mode.

Good luck..

Roberto.

0

For me it was an ISAPI module called UrlScan which I had to completely remove from the application.

frezq
  • 653
  • 8
  • 18