在Web API应用程序中响应HTTP Post调用时,我应该使用“[FromBody]”值还是自定义参数?

时间:2015-12-29 20:09:19

标签: asp.net-web-api http-post asp.net-web-api-routing http-post-vars frombodyattribute

POST是否使用正确的HTTP方法/动词来告诉服务器使用哪个条件来检索数据,然后将其保存在本地?

我想从客户端(Windows窗体)app / util向我的Web API应用程序发送一个URL,告诉它通过Stored Proc检索数据,然后将结果存储在本地表中。没有数据返回给调用者,它只是做一些工作的通知。

为了做好准备,我添加了一条到WebApiConfig的新路线:

// Some reports (monthly) only need a begindate, such as "201509"; others need a range 
//  of 2..13 months, such as "2001502" and "201602")
config.Routes.MapHttpRoute(
    name: "ReportsApi",
    routeTemplate: "api/{controller}/{unit}/{begindate}/{enddate}",
    defaults: new { enddate = RouteParameter.Optional }
);

在Controller中,此方法已存在(已自动添加):

// POST: api/PriceCompliance
public void Post([FromBody]string value)
{
}

...但我不知道我是否想要“[FromBody]”爵士乐,所以我补充说:

public void Post(String unit, String beginDate, String endDate)
{
    // TODO: Call the corresponding SP (via a Model or directly here?) and store the results in a table.
}

这是正确/更好的方法,还是最好从“[FromBody]”中提取URL args?事实上,POST是否是正确的HTTP动词用于此类事情?

1 个答案:

答案 0 :(得分:1)

为你的行动选择正确的动词总是有争议的。如果您查看 RFC 7231 的项目4.3.3:

  

POST方法请求目标资源进程   根据资源的要求包含在请求中的表示   拥有特定的语义。例如,POST用于以下
  功能(等等):

     
      
  • 提供数据块,例如输入的字段   HTML     表格,数据处理流程;
  •   

其中的关键字以粗体突出显示。正如您所看到的,它非常适合您的情况,您发送带有数据块的POST请求,而某些进程由您的API生成。

关于POST中如何处理参数的问题。您可以创建DTO来映射您的字段:Unit, BeginDate, EndDate。由于您是从body发送参数,因此WebAPI将使用Formatter绑定参数。 WebAPI将根据content-type header.选择更好的格式化程序。在我提供的示例中,使用的格式化程序将是JSON.Net(这是JSON的默认格式)

<强> PriceComplianceDTO

public class PriceComplianceDTO
{
    public string Unit { get; set; }

    public DateTime BeginDate { get; set; }

    public DateTime EndDate { get; set; }
}

<强>控制器

[RoutePrefix("api/v1")]
public class PriceComplianceController : ApiController
{
    [HttpPost]
    [Route("price")]
    public void Post(PriceComplianceDTO data)
    {
        //Call procedure and process data
    }
}

如果您决定使用上述方法,还可以删除从WebApiConfig发布的自定义路线。我刚刚创建了一个新的Web API,这是我的默认路由,它使用POST:

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