【问题标题】:Routing all POST request to 1 APIController method which receives the POST body将所有 POST 请求路由到 1 个接收 POST 正文的 APIController 方法
【发布时间】:2018-09-11 15:56:37
【问题描述】:

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

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

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

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

        var requestPath = Request.RequestUri.LocalPath;

        return jsonBody;
    }
}      

【问题讨论】:

  • 听起来像是 x/y 问题。你打算怎么做?
  • 在不回答您的具体问题的情况下,我会注意到这是一个非常不寻常的设计,并且在所有 RESTful 方面都是苍蝇。 REST 定义了一系列资源,每个资源都位于一个给定的端点。您正在尝试为每个资源创建一个端点。在这种情况下,如果您能解释您实际尝试解决的设计问题,将会有所帮助。也许有更好的方法来完成它。
  • 我理解对设计的担忧。目前只是在试验 WebApi,并将其与我已经在使用 HTTPHandlers 做的比较。
  • 尝试在操作方法上将路由定义为[Route("")]

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


【解决方案1】:

尝试在 [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>\?|(=.*?))?}  

使用this 工具我发现 [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"

【讨论】:

  • 您能否解释一下为什么这适用于路径 localhost/api/user/123/orders/100 而无需修改正则表达式以包含 0-9 ?
  • 我不知道,但我打算查看源代码以了解它的工作原理,然后我会回信给您
  • 我发现了原因并编辑了我的答案。最好的问候
猜你喜欢
  • 2012-04-03
  • 2015-02-02
  • 2020-11-24
  • 2015-09-18
  • 2022-06-25
  • 2018-04-02
  • 2019-04-03
  • 2019-03-29
  • 1970-01-01
相关资源
最近更新 更多