ASP.NET WebAPI 返回 Http 405

ASP.NET WebAPI returning Http 405

我有一个 WebApi 控制器

[RoutePrefix("api/invitations")]
public class InvitationsApiController : ApiController

以及动作方法:

[Route]
[HttpPost]
public IHttpActionResult Create([FromBody] CreateCommand command)

当我尝试 POST 到 http://host/api/invitations 时,我收到““405 方法不允许”[=1​​9=]

但是当我使用另一条路线时:

[Route("test")]
[HttpPost]
public IHttpActionResult Create([FromBody] CreateCommand command)

WebApiConfig.cs

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
    SetupFormatters(config);

    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi", 
        routeTemplate: "api/{controller}/{id}", 
        defaults: new { id = RouteParameter.Optional });
}

并使 POST 到 http://host/api/invitations/test 正常工作。我的控制器在请求 "root" 时工作得非常完美。

有关 Http 错误的更多详细信息:

HTTP Error 405.0 - Method Not Allowed The page you are looking for cannot be displayed because an invalid method (HTTP verb) is being used.

Detailed Error Information: 
Module    DefaultDocumentModule
Notification    ExecuteRequestHandler  
Handler    StaticFile  Error
Code    0x80070001  
Requested URL   http://localhost:8008/api/invitations  
Physical Path <removed>   
Logon Method  Anonymous  
Logon User    Anonymous

有什么建议可能是错误的吗?

在控制器级别将您的控制器 RoutePrefix 声明更改为 Route

[Route("api/invitations")]
public class InvitationsApiController : ApiController

RoutePrefix 不会将路由添加到路由 table。这意味着,如果您想使用 RoutePrefix,则必须为每个操作单独添加前缀,例如:

[RoutePrefix("api/invitations")]
public class InvitationsApiController : ApiController

[Route("")]
[HttpPost]
public IHttpActionResult Create([FromBody] CreateCommand command)

问题是您有一个与您的路由匹配的物理目录 (/api/invitations)。因为存在这样的物理目录,IIS 本机 DirectoryListingModuleDefaultDocumentModule 模块(不允许 POST 动词)在 TransferRequestHandler(由MVC 和 WebAPI) 能够处理它。

没有理由将您的 InvitationsController.cs 放在与请求的路由匹配的同一目录结构中。这就是为什么我们首先要有路由,以便能够动态注册路由,而不管控制器的物理位置如何。

通常的约定(这也是默认的 WebAPI 模板结构)是将您的控制器放在 ~/Controllers 目录(或 ~/Controllers/Api)中。但实际上您可以将它们放在任何目录中,只要它们作为项目的一部分进行编译即可。