首页 > 解决方案 > 将所有 POST 请求路由到 1 个接收 POST 正文的 APIController 方法

问题描述

我试图在我的 ApiController 中配置一个方法来处理所有 POST 请求,无论路径段的数量如何,并接收始终为 json 的 post 正文。我已经尝试了几种通配符表和属性路由的变体,但无法使其适用于具有超过 1 个路径段的请求。

另外,我不知道如何在方法中接收整个 json 主体。

[RoutePrefix("api")]
public class MyController: ApiController
{

    [HttpPost]
    [Route("*")]
    public string PostHandler([FromBody]string jsonBody)
    {

        var requestPath = Request.RequestUri.LocalPath;

        return jsonBody;
    }
}      

标签: c#asp.net-web-apiasp.net-apicontroller

解决方案


尝试在 [Route()] 中使用正则表达式通配符并且不要指定 [RoutePrefix]。还可以尝试直接从请求中获取正文作为字符串,这应该可以。

public class MyController: ApiController
{

    [HttpPost]
    [Route("api/{*[a-zA-Z]}")]
    public string PostHandler()
    {
        string result = Request.Content.ReadAsStringAsync().Result;   
        var requestPath = Request.RequestUri.LocalPath;

        return result;
    }
}   

如果您想使用异步,请尝试以下代码:

public class MyController: ApiController
{

    [HttpPost]
    [Route("api/{*[a-zA-Z]}")]
    public async Task<string> PostHandler()
    {
        string result = await Request.Content.ReadAsStringAsync();   
        var requestPath = Request.RequestUri.LocalPath;

        return result;
    }
} 

编辑

[Route("api/{*asd}")]{*[a-zA-Z]}部分不做任何事情,而是 MVC 堆栈使用正则表达式验证每个路由:

{(?<parameterName>.+?)(:(?<constraint>.*?(\(.*?\))?))*(?<defaultValue>\?|(=.*?))?}  

使用这个工具,我发现 [a-zA-Z] 是 parameterName 组的一部分,并被用作将值注入到动作参数中。

如果我们使用

public class MyController: ApiController
{

    [HttpPost]
    [Route("api/{*path}")]
    public string PostHandler(string path)
    {
        string result = Request.Content.ReadAsStringAsync().Result;   
        var requestPath = Request.RequestUri.LocalPath;

        return result;
    }
}   

并调用 /api/user/123/orders/100,然后:

path = "user/123/orders/100" 
requestPath = "/api/user/123/orders/100"

推荐阅读