Routing not working when sending a DELETE request to an HttpDelete action
Asked Answered
C

5

5

I have a ProductsController with only one View - Index.cshtml.

The following 3 action methods are inside of this controller:

//http://localhost:55555/products
[HttpGet]
public IActionResult Index()
{
}

//http://localhost:55555/products
[HttpPost]
public IActionResult Index(ProductViewModel product)
{
}

//http://localhost:55555/products/1
[HttpDelete("{id}")]
public IActionResult Index([FromRoute] int id)
{
}

Get works perfectly fine when I go to /products. Post works perfectly fine when I create a new product using /products. Delete does not work at all, I am getting a 404 not found for /products/9. I am using a standard AJAX request w/ type: DELETE.

I am using the default MVC conventional routing settings:

        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");

Here is what my AJAX Request looks like:

$(".js-delete-product").click(function () {
    $.ajax({
        type: "DELETE",
        url: "products/" + $(this).data("id"),
        success: onDeleteSuccess
    });
});

I also tried sending a DELETE request in postman to http://localhost:55555/products/1 to make sure it wasn't my jquery ajax and still 404 not found.

UPDATE: If I send a DELETE request to just http://localhost:55555/products it goes into the function, but as you would expect the id param is set to null. Any idea why this is happening? I only want it to go into the delete method if a param is passed, but when a param is passed it doesn't go in (404 not found).

Canonicate answered 19/12, 2016 at 17:43 Comment(5)
Could you please try to send a DELETE request to http://localhost:55555/products/index/1 and see if that works?Unconformable
Can you post your Ajax code?Access
@Dobbins I updated my post with the ajax code. I have no idea why it wouldn't work. The console is throwing a 404 not found error and is telling me that the requested url is: localhost:555555/products/1Canonicate
@rabelloo Still getting a 404 not found.Canonicate
Please see the update at the bottom of my post.Canonicate
S
4

Include the route parameter for id on the [HttpDelete] attribute:

[HttpDelete("{id}")]
public IActionResult Index([FromRoute] int id)
{
}
Subarid answered 19/12, 2016 at 18:33 Comment(1)
I really thought this was going to work, but it does not.Canonicate
T
3

For me the issue was related to this: https://weblog.west-wind.com/posts/2015/Apr/09/ASPNET-MVC-HttpVerbsDeletePut-Routes-not-firing

Out of the box only a few verbs are handled for extension-less URLs. The solution is to update your web.config to explicitly specify the accepted verbs.

 <configuration>
   <system.webServer>
      <handlers>
        <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
        <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." 
             verb="GET,HEAD,POST,DEBUG,PUT,DELETE,OPTIONS" 
             type="System.Web.Handlers.TransferRequestHandler" 
             preCondition="integratedMode,runtimeVersionv4.0" />
      </handlers>
    </system.webServer>
</configuration>
Tiedeman answered 27/2, 2019 at 3:8 Comment(0)
C
2

Finally found the answer to this, but only from trial and error. I have no idea why it only works this way.

//http://localhost:55555/products/1

[HttpDelete("products/{id}")]
public IActionResult Index([FromRoute] int id)
{
}

I have no idea why I should have to specify the controller name as it should already be assumed based off of this setting:

    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");

If someone can further explain why this is the case that would be great.

Canonicate answered 19/12, 2016 at 20:0 Comment(2)
Apparently the template is not parsed the way you expected, therefore you are not able to set defaults and optional parameters within it. You must set it up like @Steve suggested. Here's MS documentation: msdn.microsoft.com/en-us/library/cc668201.aspxUnconformable
[HttpDelete] doesn't take any arguments (as of the latest MVC I'm using) so this doesn't compileGaberdine
D
0

for route you can mark certain fields as optional and set the default for others

routes.MapRoute(
   name: "default",
   template: "{controller}/{action}/{id}", 
   defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional});

then you can just do

[HttpDelete]
public IActionResult Index(int id)
{
}
Dara answered 19/12, 2016 at 19:27 Comment(2)
I believe that is the same thing as the configuration specified in my post. Correct me if I am wrong.Canonicate
@BlakeRivell not sure if the from route tag has any conflict with the {id} attribute. give it a shotDara
R
0
 [HttpDelete("{Id}")]
    public IActionResult Delete(int? Id)
    {
        if (Id == null)
        {
            return BadRequest();
        }
        Item itemToRemove = Repo.Find(Id);
        if (itemToRemove == null)
        {
            return BadRequest();
        }
        Repo.Delete(itemToRemove );
        return NoContent();
    }

and make the call like this: /products/5

Rabia answered 1/8, 2018 at 1:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.