Маршрутизация не работает при отправке запроса DELETE в действие HttpDelete

У меня есть ProductsController только с одним представлением — Index.cshtml.

Внутри этого контроллера находятся следующие 3 метода действия:

//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 отлично работает, когда я захожу в /products. Post отлично работает, когда я создаю новый продукт, используя /products. Удаление вообще не работает, я получаю 404 не найдено для /products/9. Я использую стандартный запрос AJAX с типом: DELETE.

Я использую стандартные настройки маршрутизации MVC по умолчанию:

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

Вот как выглядит мой запрос AJAX:

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

Я также попытался отправить запрос DELETE в почтальоне на http://localhost:55555/products/1 для убедитесь, что это не мой jquery ajax и все еще 404 не найден.

ОБНОВЛЕНИЕ: если я отправлю запрос DELETE только на http://localhost:55555/products он входит в функцию, но, как и следовало ожидать, для параметра id установлено значение null. Любая идея, почему это происходит? Я хочу, чтобы он перешел в метод удаления только в том случае, если передан параметр, но когда параметр передан, он не входит (404 не найден).


person Blake Rivell    schedule 19.12.2016    source источник
comment
Не могли бы вы попробовать отправить запрос DELETE на http://localhost:55555/products/index/1 и посмотреть, сработает ли это?   -  person rabelloo    schedule 19.12.2016
comment
Можете ли вы опубликовать свой код Ajax?   -  person Scott Dobbins    schedule 19.12.2016
comment
@Dobbins Я обновил свой пост кодом ajax. Я понятия не имею, почему это не сработает. Консоль выдает ошибку 404 not found и сообщает мне, что запрошенный URL-адрес: localhost:555555/products/1   -  person Blake Rivell    schedule 19.12.2016
comment
@rabelloo Все еще получаю 404 не найдено.   -  person Blake Rivell    schedule 19.12.2016
comment
Пожалуйста, смотрите обновление внизу моего поста.   -  person Blake Rivell    schedule 19.12.2016


Ответы (5)


Включите параметр маршрута для id в атрибут [HttpDelete]:

[HttpDelete("{id}")]
public IActionResult Index([FromRoute] int id)
{
}
person Justin Saraceno    schedule 19.12.2016
comment
Я действительно думал, что это сработает, но это не так. - person Blake Rivell; 19.12.2016

для маршрута вы можете пометить определенные поля как необязательные и установить значения по умолчанию для других

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

то вы можете просто сделать

[HttpDelete]
public IActionResult Index(int id)
{
}
person Steve    schedule 19.12.2016
comment
Я считаю, что это то же самое, что и конфигурация, указанная в моем посте. Поправьте меня, если я ошибаюсь. - person Blake Rivell; 19.12.2016
comment
@BlakeRivell не уверен, что тег маршрута from конфликтует с атрибутом {id}. дать ему шанс - person Steve; 19.12.2016

Для меня проблема была связана с этим: https://weblog.west-wind.com/posts/2015/Apr/09/ASPNET-MVC-HttpVerbsDeletePut-Routes-not-Firing

По умолчанию только несколько глаголов обрабатываются для URL-адресов без расширения. Решение состоит в том, чтобы обновить ваш web.config, чтобы явно указать допустимые глаголы.

 <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>
person davidp_1978    schedule 27.02.2019

Наконец нашел ответ на этот вопрос, но только методом проб и ошибок. Я понятия не имею, почему это работает только таким образом.

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

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

Я понятия не имею, почему я должен указывать имя контроллера, поскольку оно уже должно быть принято на основе этого параметра:

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

Если кто-то может объяснить, почему это так, это было бы здорово.

person Blake Rivell    schedule 19.12.2016
comment
Очевидно, что шаблон анализируется не так, как вы ожидали, поэтому вы не можете установить в нем значения по умолчанию и необязательные параметры. Вы должны настроить его, как предложил @Steve. Вот документация MS: msdn.microsoft.com/en-us/library/cc668201. aspx - person rabelloo; 20.12.2016
comment
[HttpDelete] не принимает никаких аргументов (начиная с последней версии MVC, которую я использую), поэтому это не компилируется - person PandaWood; 17.04.2019

 [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();
    }

и сделайте вызов следующим образом: /products/5

person Alejandro Haro    schedule 01.08.2018