.NET 核心 2.2。尝试删除时如何消除此 HTTP 405 错误?

1 c# iis-express asp.net-core asp.net-core-2.2

当我尝试通过删除来执行简单的帖子时,出现 405 错误。我可以很好地读取、写入和更新,但无法弄清楚为什么 Visual Studio 2017(或者更具体地说,IIS Express)不允许我执行删除。

\n\n

互联网上有很多关于 的帖子web.config,但它们都是较旧的帖子,最近的帖子不起作用。事实上,web.config我的项目中没有包含它,因为我相信微软正在走向appsettings.json

\n\n

我正在 Docker 容器中运行 Visual Studio 2017 v15.9.11 和 .NET Core 2.2。我切换到 IIS Express 但没有运气。我已经查看了applicationhost.configIIS Express 的文件,并且 WebDav 已被注释掉。我相信它发生在网络服务器级别,因为我在调试时没有受到控制器的影响。我最好的猜测是某个地方有一个默认设置不允许删除;我就是找不到它。

\n\n

模型

\n\n
namespace Efficacy.Models.Entities\n{\n    /* dbo.Contact.Contact */\n    public class Contact\n    {\n        private const string V = "First Name";\n\n        public int Id { get; set; }\n        public ContactType ContactType { get; set; }\n        public int ContactTypeId { get; set; }\n\n        [Required]\n        //[Display( Description = ("Delete")]\n        public string FirstName { get; set; }\n        public string MiddleName { get; set; }\n        [Required]\n        public string LastName { get; set; }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

数据库上下文

\n\n
namespace Efficacy.Data\n{\n    public class EfficacyDBContext : DbContext\n    {\n        public virtual DbSet<Contact> Contact { get; protected set; }\n        public virtual DbSet<ContactType> ContactType { get; protected set; }\n        public virtual DbSet<HelloNurse> HelloNurse { get; protected set; }\n\n        public EfficacyDBContext(DbContextOptions options) : base(options)\n        {\n        }\n\n        protected override void OnModelCreating(ModelBuilder modelBuilder)\n        {\n            modelBuilder.ApplyConfiguration(new ContactEntityTypeConfiguration());\n            modelBuilder.ApplyConfiguration(new ContactTypeEntityTypeConfiguration());\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

控制器

\n\n
namespace Efficacy.Areas.Ops.Controllers\n{\n    [Area("Ops")]\n    public class ContactController : Controller\n    {\n        private readonly EfficacyDBContext _db;\n\n        public ContactController(EfficacyDBContext db)\n        {\n            _db = db;\n        }\n\n        [HttpPost]\n        [ValidateAntiForgeryToken]\n        public async Task<IActionResult> ContactDelete(int id)\n        {\n            var contact = await _db.Contact.FindAsync(id);\n\n            if (contact == null)\n            {\n                return NotFound();\n            }\n\n            _db.Contact.Remove(contact);\n            await _db.SaveChangesAsync();\n\n            return RedirectToAction(nameof(Index));\n        }\n\xe2\x80\xa6 \n
Run Code Online (Sandbox Code Playgroud)\n\n

看法

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

控制台输出

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

启动.cs

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

Ale*_*der 6

405HTTP 代码的含义是Method Not Allowed. Served 返回此错误,因为操作需要POST请求(因为它标有[HttpPost]),并且当用户单击锚标记 ( <a>) 时浏览器发送GET请求。为了发送POST您需要使用form标签

<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>
Run Code Online (Sandbox Code Playgroud)

此外,您还具有[ValidateAntiForgeryToken]操作属性,因此需要发送防伪令牌。FormTagHelper会自动input为您生成隐藏的令牌,因此您无需执行任何其他操作。