.Net Core 2.2.Как избавиться от этой надоедливой ошибки HTTP 405 при попытке удалить? - PullRequest
1 голос
/ 08 апреля 2019

Я получаю ошибку 405 при попытке сделать простой пост с удалением. Я могу читать, писать и обновлять просто отлично, но не могу понять, почему VS 2017 (или, точнее, IIS Express) не позволяет мне удалять.

В сети есть много web.config this и web.config that, но это старые посты, а последние не работают. На самом деле, в моем проекте не было web.config, потому что MS движется в сторону appsettings.json. Я использую VS2017 v 15.9.11 (Core 2.2), используя Docker. Перешел на IIS Express без везения. Я посмотрел файл applicationhost.config для IIS Express, и WebDav уже закомментирован. ИМХО, я думаю, что это происходит на уровне веб-сервера, потому что я не получаю удар по контроллеру при отладке. Итак, мое лучшее предположение, что где-то есть настройка по умолчанию, которая не позволяет удалять. Я просто не могу его найти.

Модель

namespace Efficacy.Models.Entities
{
    /* dbo.Contact.Contact */
    public class Contact
    {
        private const string V = "First Name";

        public int Id { get; set; }
        public ContactType ContactType { get; set; }
        public int ContactTypeId { get; set; }

        [Required]
        //[Display( Description = ("Delete")]
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        [Required]
        public string LastName { get; set; }
    }
}

DbContext

namespace Efficacy.Data
{
    public class EfficacyDBContext : DbContext
    {
        public virtual DbSet<Contact> Contact { get; protected set; }
        public virtual DbSet<ContactType> ContactType { get; protected set; }
        public virtual DbSet<HelloNurse> HelloNurse { get; protected set; }

        public EfficacyDBContext(DbContextOptions options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfiguration(new ContactEntityTypeConfiguration());
            modelBuilder.ApplyConfiguration(new ContactTypeEntityTypeConfiguration());
        }
    }
}

Контроллер

namespace Efficacy.Areas.Ops.Controllers
{
    [Area("Ops")]
    public class ContactController : Controller
    {
        private readonly EfficacyDBContext _db;

        public ContactController(EfficacyDBContext db)
        {
            _db = db;
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> ContactDelete(int id)
        {
            var contact = await _db.Contact.FindAsync(id);

            if (contact == null)
            {
                return NotFound();
            }

            _db.Contact.Remove(contact);
            await _db.SaveChangesAsync();

            return RedirectToAction(nameof(Index));
        }
...

View

@model Efficacy.Models.Entities.Contact
@{
    ViewData["Title"] = "Add Contact";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container-fluid">
    <div class="row">
        <div class="col-6">
            <h2 class="text-info">Add Contact</h2>
        </div>
        <div class="col-6 text-right">
            &nbsp
        </div>
    </div>
    <div>
        <form method="post" asp-area="Ops" asp-controller="Contact"  
                asp-action="ContactDelete">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <table class="table table-striped border shadow p-3 mb-5 bg-white rounded">
                <tr class="table-secondary">
                    <th><label asp-for="FirstName">First Name</label></th>
                    <th><label asp-for="MiddleName">Middle</label></th>
                    <th><label asp-for="LastName">Last Name</label></th>
                    <th><label asp-for="ContactTypeId">Contact Type</label></th>
                    <th class="text-right">&nbsp;</th>
                </tr>
                <tr>
                    <td>
                        <input asp-for="FirstName" class="form-control"
                               value="@Model.FirstName" />
                        <span asp-validation-for="FirstName"
                              class="text-danger"></span>
                    </td>
                    <td>
                        <input asp-for="MiddleName" class="form-control"
                               value="@Model.MiddleName" />
                        <span asp-validation-for="FirstName"
                              class="text-danger"></span>
                    </td>
                    <td>
                        <input asp-for="LastName" class="form-control"
                               value="@Model.LastName" />
                        <span asp-validation-for="FirstName"
                              class="text-danger"></span>
                    </td>
                    <td>
                        @* TODO:  Bind *@
                        <select name="ContactTypeId" class="form-control">
                            <option value="1">Organization</option>
                            <option value="2">Lead</option>
                            <option value="3">Event</option>
                            <option value="4">Invoice</option>
                            <option value="5">Contact</option>
                        </select>
                    </td>
                    <td class="text-right">
                        <input type="submit" class="btn btn-info form-control mb-1"
                               asp-route-id="@Model.Id" value="Save" />
                        <a asp-area="ops" asp-controller="Contact"
                           asp-action="ContactDelete" asp-route-id="@Model.Id"
                           class="btn btn-danger form-control mb-1">Delete</a>
                        <a asp-action="Index"
                           class="btn btn-success form-control">Cancel</a>
                    </td>
                </tr>
            </table>
        </form>
    </div>
</div>

Консольный вывод

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET https://localhost:44382/Ops/Contact/ContactDelete/11  
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:44382/Ops/Contact/ContactDelete/11  
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '405 HTTP Method Not Supported'
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executing endpoint '405 HTTP Method Not Supported'
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint '405 HTTP Method Not Supported'
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '405 HTTP Method Not Supported'
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 14.0081ms 405 

Startup.cs

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "areas",
        template: "{area=Ops}/{controller=Home}/{action=Index}/{id?}");
});

Ответы [ 2 ]

3 голосов
/ 08 апреля 2019

405 Код HTTP означает Method Not Allowed.Служба вернула эту ошибку, потому что действие ожидает запрос POST (поскольку он помечен [HttpPost]), и когда пользователь щелкает тег привязки (<a>), браузер отправляет запрос GET.Чтобы отправить POST, вам нужно использовать form tag

<form method="post" asp-action="ContactDelete" asp-area="Ops" asp-controller="Contact">
    <input name="Id" value="@item.Id" type="hidden" /> <!-- hidden input contains Id value -->
    <button type="submit">Delete</button>
</form>

Также у вас есть атрибут [ValidateAntiForgeryToken] для действия, поэтому для отправки требуется маркер защиты от подделки. FormTagHelper автоматически сгенерирует скрытый input с этим токеном для вас, поэтому вам больше ничего не нужно делать.

1 голос
/ 08 апреля 2019

я считаю, что ваша проблема связана с маршрутизацией Вы можете попробовать это.

    [HttpPost("id")] <----------
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> ContactDelete([FromRoute(Name = "id" )] int id) <----------
    {
        var contact = await _db.Contact.FindAsync(id);

        if (contact == null)
        {
            return NotFound();
        }

        _db.Contact.Remove(contact);
        await _db.SaveChangesAsync();

        return RedirectToAction(nameof(Index));
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...