【问题标题】:.Net Core 2.2 Web API 405.Net Core 2.2 Web API 405
【发布时间】:2019-07-22 15:32:27
【问题描述】:

我正在尝试设置一个 .net core 2.2 web api 来使用后置动词。无论是在我的本地计算机 (w10 iis eXPRESS 10.0) 还是 windows 服务器 (2016 R2 IIS 8.0) 上运行,除了 get 动词之外的任何内容都会返回 405。我已经阅读了有关在配置文件中禁用 WebDav、添加路由和完全删除 WebDav 功能的其他帖子。我做了所有这些都无济于事。我刚刚开始在核心中开发并发现这令人困惑,在同一台服务器上是一个在 .net 框架 4.5 上运行的非核心 Web api,它可以毫无错误地处理 GET、PUT、POST、DELETE。是的,我在更改任何配置后重新启动了服务器。以下是我所做的 web.config 更改,最后一个直接来自 MS。在我的机器和服务器上重现相同错误的基本项目在这里 https://github.com/FranciscanMedia/error405_core/tree/master 它只是您启动 VS2019 时获得的标准 Web api 项目。

<system.webServer>    
    <handlers accessPolicy="Read, Script">
       <remove name="WebDAV" />
       <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
       <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"
          path="*."
          verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
          modules="IsapiModule"
          scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
          preCondition="classicMode,runtimeVersionv4.0,bitness64"
          responseBufferLimit="0" />
    </handlers>
</system.webServer>
<system.webServer>    
    <modules>        
        <remove name="WebDAVModule" />    
    </modules>    
    <handlers>        
        <remove name="WebDAV" />    
    </handlers>
</system.webServer>
<system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="false">
        <remove name="WebDAVModule"/>
    </modules>    
</system.webServer>
<system.webServer>
    <handlers accessPolicy="Read, Script">
        <remove name="WebDAV" />
        <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
        <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"
           path="*."
           verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
           modules="IsapiModule"
           scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
           preCondition="classicMode,runtimeVersionv4.0,bitness64"
           responseBufferLimit="0" />
    </handlers>
</system.webServer>

【问题讨论】:

  • 当你在本地使用 dotnet cli 运行时会发生什么?
  • @joey 发生了同样的事情,尽管命令行可能会放弃更多问题,但似乎 Microsoft.AspNetCore.Routing.EndpointMiddleware 正在将 405 吐出。 [屏幕抓取] (pasteboard.co/IpbSUEd.jpg)
  • "可能会放弃更多的问题" 不确定这意味着什么。尝试使用此处所述的最少代码在公共 github 存储库中创建问题。在那之后你一定会得到解决stackoverflow.com/help/minimal-reproducible-example
  • @joey 这只是意味着我在使用浏览器和 POSTMAN 时没有收到除 405 以外的消息,CLI 为我提供了产生错误的命名空间(如屏幕截图所示)Microsoft.AspNetCore .路由.中间件。仍然找不到任何关于它的信息。我启动了一个核心 web api 项目并在我的机器/服务器上运行它,结果相同。可以在这里找到:github.com/FranciscanMedia/error405_core/tree/master
  • 你了解过这个吗?我遇到了完全相同的问题。

标签: c# .net webdav visual-studio-2019 .net-core-2.2


【解决方案1】:

简答

可能就这么简单。原因是路由。

只需将您的 POST 请求发送到正确的 URL,例如 https://localhost:44327/api/values/123。


详细解释

这不是问题。它按预期工作。

您向https://localhost:44327/api/values/ 发出GET 请求。它返回200 OK。

但是当您向同一 URL https://localhost:44327/api/values/ 发出 POST 请求时。上面写着405 Method not allowed。

但是,您会得到405。发生这种情况是因为您使用 POST 方法访问了 GET 端点。

微软文档说:

... HTTP 客户端向 Web 服务器上的 Web API 应用程序的 URL 发送了一个有效的 JSON 请求,但服务器返回了一条 HTTP 405 错误消息,表明该 URL 不允许使用 PUT 方法。相反,如果请求 URI 与 Web API 应用程序的路由不匹配,服务器将返回 HTTP 404 Not Found 错误。

https://docs.microsoft.com/en-us/aspnet/web-api/overview/testing-and-debugging/troubleshooting-http-405-errors-after-publishing-web-api-applications

如果您只是删除 GET 端点。 POST 请求将开始返回 404 Not found。这意味着您没有到达任何已注册的路线。

发送POST请求需要根据路由规则使用不同的URL。

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{

    // POST api/values
    [HttpPost("{val}")]
    public StatusCodeResult Post()
    {
        return Ok();
    }
}

这个基于属性的配置意味着你的POST端点的路由是/api/Values/{val}。其中{val} 是任何值。它不在端点中处理。

如果你想处理它,你应该把它传递给方法:

[HttpPost("{val}")]
public StatusCodeResult Post(string val)
{
    return Ok();
}

【讨论】:

  • 没有完全看代码库,但可能是答案
  • 您的回答解决了我的问题。我的代码与 OP 的代码略有不同,但是当我注释掉 GET 操作时,405 更改为 404,所以这是一个路由问题。谢谢!
【解决方案2】:

我认为在您的控制器中您必须导入另一个库。 试试

using System.Web.Http;

代替

using Microsoft.AspNetCore.Mvc

【讨论】:

    【解决方案3】:

    看看你定义了什么:

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    

    那么对于动作:

    [HttpPost("{val}")]
    public StatusCodeResult Post()
    {
            return Ok();
    }
    

    您的路由与以下网址匹配:

    https://localhost:44327/api/values/StatusCodeResult

    它将采用您在控制器上定义的主路由 [Route("api/[controller]")]

    然后您定义“模板”以使用“{val}”

    这告诉它使用 ActionResult 特定名称并期望 var val 被传递/附加。

    在此处查看官方文档:https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-2.2

    在“路由模板中的令牌替换([控制器]、[动作]、[区域])”部分下

    他们指定:

    为方便起见,属性路由通过将标记括在方括号 ([, ]) 中来支持标记替换。标记 [action]、[area] 和 [controller] 被替换为定义路由的操作中的操作名称、区域名称和控制器名称的值。在以下示例中,操作与 cmets 中所述的 URL 路径匹配:

    [Route("[controller]/[action]")]
    public class ProductsController : Controller
    {
      [HttpGet] // Matches '/Products/List'
      public IActionResult List() {
        // ...
      }
    
      [HttpGet("{id}")] // Matches '/Products/Edit/{id}'
      public IActionResult Edit(int id) {
        // ...
      }
    }
    

    如果您希望它仅基于动词进行路由(遵循每个 api 端点仅处理该特定对象的操作的模式),那么您可以将您的 post 方法更改为仅

        [HttpPost]
        public ActionResult Post(string val)
        {
            return Ok();
        }
    

    【讨论】:

      【解决方案4】:

      我完全同意@Vladimir 的回答。我没有足够的积分将 cmets 添加到@vlaimir 的answer,所以我添加了我的想法和建议。

      你的 github 上的代码,

      // POST api/values
      [HttpPost("{val}")]
      public StatusCodeResult Post()
      {
           return Ok();
      }
      

      这是一个帖子,它期望每个路由操作配置的值 {val}。由于您可能会尝试在没有任何价值的情况下点击帖子,因此这是不允许的。确保您提供一些值,然后执行 POST。如果您使用的是 POSTMAN,您可能需要为请求的 BODY 提供一些值。 Swagger 是一个很好的嵌入到 web api 的实用工具,它为我们的路由/资源提供了出色的直观 UI。这甚至可能是帮助确定和确保您提供正确价值的理想选择。

      否则,您无需修改​​或担心您的 IIS 或 IIS Express 设置。或 webdav。

      【讨论】:

        猜你喜欢
        • 2019-08-06
        • 1970-01-01
        • 2020-01-26
        • 2019-07-01
        • 2020-09-09
        • 2020-04-10
        • 2019-07-21
        • 2019-11-05
        • 1970-01-01
        相关资源
        最近更新 更多