在POST API中传递多个参数,而不使用.Net Core MVC中的DTO类

egm*_*frs 5 .net c# asp.net-mvc json asp.net-core-webapi

我在我的web项目上有一个调用API的操作

    [HttpPost]
    public async Task<IActionResult> ExpireSurvey(int id)
    {
        var token = await HttpContext.GetTokenAsync("access_token");

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);

            var path = "/api/forms/ExpireSurvey";
            var url = Domain + path;
            var data = JsonConvert.SerializeObject(id);
            HttpContent httpContent = new StringContent(data, Encoding.UTF8, "application/json");
            var response = await client.PutAsync(url, httpContent);

            return Json(response);
        }
    }
Run Code Online (Sandbox Code Playgroud)

在API项目中,收到如下:

[HttpPut]
    public IActionResult ExpireSurvey([FromBody] int surveyId)
    {
        _repository.ExpireSurvey(surveyId, expiryDate);
        return Ok();
    }
Run Code Online (Sandbox Code Playgroud)

这工作正常 - 但是,我想要传入一个int id和一个DateTime变量,我如何序列化并将它们传递给HttpContent?我可以用DTO对象来做,但是当只有两个字段时我不想设置DTO对象.

Han*_*ian 8

您可以使用这样的匿名类型

var x = new { id = 2, date = DateTime.Now };
var data = JsonConvert.SerializeObject(x);
Run Code Online (Sandbox Code Playgroud)

接收数据时,您只能有一个[FromBody]参数.因此,这不适用于接收多个参数(除非您可以将所有参数放入URL中).如果您不想声明DTO,可以使用如下动态对象:

[HttpPost]
public void Post([FromBody] dynamic data)
{
    Console.WriteLine(data.id);
    Console.WriteLine(data.date);
}
Run Code Online (Sandbox Code Playgroud)

但是,不要过度使用匿名类型和动态变量.它们使用JSON非常方便,但是你丢失了所有类型检查,这是使C#非常好用的事情之一.

  • 不,我已经扩展了我的答案,以涵盖接收数据. (2认同)

Chr*_*att 5

我认为认识到ASP.NET Core是基于REST的并且REST从根本上处理资源的概念将很有帮助。虽然这不是牢不可破的规则,但总的想法是您应该在这里拥有所谓的DTO。换句话说,您不是要发布不同且无关的数据位,而是要表示某个对象的对象

如果您开始混入Swagger之类的东西来为您的API生成文档,这一点就变得越来越重要。您创建的对象将成为该文档的一部分,从而为API的使用者提供一个模板,供其开发应用程序时遵循。

总而言之,我会说接受资源/对象/ DTO /任何概念。为您的API使用的数据建模。它将对您作为API的开发人员以及您的API的使用者都有帮助。


Ela*_*ode 5

您可以将多个参数作为URL传递,如下例所示

参数名称必须相同(不区分大小写)。如果名称不匹配,则不会设置参数值。

[HttpPost]
[Route("{surveyId}/{expiryDate}")]
public IActionResult Post(int surveyId, DateTime expiryDate)
{
    return Ok(new { surveyId, expiryDate });
}
Run Code Online (Sandbox Code Playgroud)

通话网址

http://localhost:[port]/api/[controller]/1/3-29-2018
Run Code Online (Sandbox Code Playgroud)