20

I am having difficulty getting the DELETE Method on my Controller to fire when submitting the request over ASP.NET Web API. It returns a 404 but I cannot figure out why. The GET & POST requests work as expected, returning both a list of items as well as a single item when provided an id, but when I call the API using a DELETE request I get a 404 ERROR.

Scenario:

1. ASP.NET Web Forms application ...

Not an MVC application although I have installed the MVC4 package in order to leverage the Web API features.

2. Route Table definition in global.asax

            RouteTable.Routes.MapHttpRoute(

                    "Default", 
                    "api/{controller}/{id}", 
                    new { id = RouteParameter.Optional } 
            );

3. Controller definition

    public HttpResponseMessage<Customer> Post(Customer customer)
    {
        CustomerDb.Customers.AddObject(customer);
        CustomerDb.SaveChanges();
        var response = new HttpResponseMessage<Customer>(customer, HttpStatusCode.Created);
        response.Headers.Location = new Uri(Request.RequestUri, "/api/Customer/"+customer.id.ToString());
        return response;
    }

    public CustomerDTO Get(int id)
    {
        CustomerDTO custDTO = null;
        Customer cust = CustomerDb.Customers.Where(c => c.id == id).SingleOrDefault();
        if (cust == null)
            throw new HttpResponseException(HttpStatusCode.BadRequest);
        else
            custDTO = new CustomerDTO(cust);
        return custDTO;
    }

    public IEnumerable<CustomerDTO> Get()
    {
        IQueryable<Customer> custs = CustomerDb.Customers.AsQueryable();

        List<CustomerDTO> dto = new List<CustomerDTO>();
        foreach (Customer cust in custs)
        {
            dto.Add(new CustomerDTO(cust));
        }

        return dto;
    }

    public Customer Delete(int id)
    {
        Customer cust = CustomerDb.Customers.Where(c => c.id == id).SingleOrDefault();
        if (cust == null)
            throw new HttpResponseException(HttpStatusCode.BadRequest);

        CustomerDb.Customers.DeleteObject(cust);
        CustomerDb.SaveChanges();
        return (cust);
    }

I have some of the methods throwing a BadRequest error instead of a 404 when a customer cannot be found so I don't get these responses confused with the REAL problem. Obviously in a real implementation a no customer would return a 404 error.

4. Ajax Call via JQuery to delete item.

function deleteCustomer(id) {

        var apiUrl = "/api/customer/{0}";
        apiUrl = apiUrl.replace("{0}", id);

        $.ajax({
            url: apiUrl,
            type: 'DELETE',
            cache: false,
            statusCode: {
                200: function (data) {
                }, // Successful DELETE
                404: function (data) {
                    alert(apiUrl + " ... Not Found");
                }, // 404 Not Found
                400: function (data) {
                    alert("Bad Request O");
                } // 400 Bad Request
            } // statusCode
        }); // ajax call
    };

SO I am expecting that the singel route map should accomodate ALL the scenarios ...

  1. GET api/customer -- Returns ALL customers
  2. GET api/customer/5 -- Returns the customer whose ID = 5
  3. POST api/customer -- Creates a new customer record
  4. DELETE api/customer/5 -- Deletes the customer whose ID = 5

1,2 & 3 work without a problem, just the DELET does not work. I have tried MANY iterations and different tweaks, to no avail. I still feel however that I am overlooking something small. I feel like the problem must be around theRoute mapping but I don't see why this route would not succesfully handle the DELETE request.

Any help would be greatly appreciated.

Thank You!

Gary

Gary O. Stenstrom
  • 2,072
  • 8
  • 34
  • 53

3 Answers3

28

Do you have this defined in your web.config?

   <system.webServer>
          <modules runAllManagedModulesForAllRequests="true">
          </modules>
    </system.webServer>
Dave Bettin
  • 2,262
  • 1
  • 17
  • 9
  • To answer your question ... No i did not ... but I SHOULD HAVE!! Works like a charm now!! Thank you very much! I'll have to look that up and see what difference it makes. This is the first I have heard of it. – Gary O. Stenstrom Mar 13 '12 at 22:45
  • 10
    Hmmm ... I did a little research and stumbled across this article advising NOT to use this technique. It offers a workaround as well. Might be worth a peek. http://www.britishdeveloper.co.uk/2010/06/dont-use-modules-runallmanagedmodulesfo.html – Gary O. Stenstrom Mar 13 '12 at 22:49
  • Was getting 404's for no obvious reason and this fixed it for me too. – Galen Apr 10 '12 at 05:30
  • 2
    Ahh just read @GaryO.Stenstrom comment above. Changed webconfig to use instead. Worked. – Galen Apr 10 '12 at 05:34
  • This SO answer also solves the problem in a similar way with the existing web.config entries: http://stackoverflow.com/questions/10906411/asp-net-web-api-put-delete-verbs-not-allowed-iis-8 – Observer Mar 22 '16 at 09:56
-1

Try returning HttpResponseMessage on your Delete method

public HttpResponseMessage Delete( string id )
{
  Customer cust = CustomerDb.Customers.Where(c => c.id == id).SingleOrDefault();
  if (cust == null)
    return new HttpResponseException( HttpStatusCode.NotFound ); // using NotFound rather than bad request

  CustomerDb.Customers.DeleteObject(cust);
  CustomerDb.SaveChanges();
  return new HttpResponseMessage( HttpStatusCode.NoContent );
}
TheRightChoyce
  • 2,954
  • 1
  • 19
  • 17
-3

You need to implement Delete method in Controller:

// DELETE /api/values/5
public void Delete(int id) {}