在 POST API 中传递多个参数,而不使用 .Net Core MVC 中的 DTO 类
Posted
技术标签:
【中文标题】在 POST API 中传递多个参数,而不使用 .Net Core MVC 中的 DTO 类【英文标题】:Post Multiple Parameters Without DTO Class 【发布时间】:2018-09-08 14:00:42 【问题描述】:我的网络项目有一个调用 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);
在 API 项目中接收如下:
[HttpPut]
public IActionResult ExpireSurvey([FromBody] int surveyId)
_repository.ExpireSurvey(surveyId, expiryDate);
return Ok();
这很好用——但是,假设我想传入一个 int id 和一个 DateTime 变量,我如何将它们序列化并将它们都传递到 HttpContent 中?我可以使用 DTO 对象来完成,但我不想在只有两个字段时设置 DTO 对象。
【问题讨论】:
using (var client = new HttpClient())
不是最好的选择,寻找它!
【参考方案1】:
你可以像这样使用匿名类型
var x = new id = 2, date = DateTime.Now ;
var data = JsonConvert.SerializeObject(x);
接收数据时,只能有一个[FromBody]参数。因此,这不适用于接收多个参数(除非您可以将除一个之外的所有参数都放入 URL)。如果不想声明 DTO,可以使用如下动态对象:
[HttpPost]
public void Post([FromBody] dynamic data)
Console.WriteLine(data.id);
Console.WriteLine(data.date);
不过,不要过度使用匿名类型和动态变量。它们对于使用 JSON 非常方便,但是您会丢失所有类型检查,这是使 C# 非常适合使用的原因之一。
【讨论】:
这将通过[HttpPut] public IActionResult ExpireSurvey([FromBody] int id, DateTime date)
很好地映射到API?
没有。我已经扩展了我的答案以涵盖接收数据。【参考方案2】:
我认为认识到 ASP.NET Core 是基于 REST 的并且 REST 从根本上处理资源的概念会很有帮助。虽然不是一个牢不可破的规则,但总体思路是您应该在这里拥有您所谓的 DTO。换句话说,您发布的不是不同且不相关的数据位,而是代表某事的 object。
如果您开始混合 Swagger 之类的东西来为您的 API 生成文档,这将变得越来越重要。您创建的对象将成为该文档的一部分,为您的 API 的使用者提供一个模板,以便在他们的应用开发中遵循。
总而言之,我想说的是接受资源/对象/DTO/其他的概念。 模型您的 API 使用的数据。作为 API 的开发者和您的 API 的任何消费者,它都会有所帮助。
【讨论】:
感谢您的信息。如果只有一个字段怎么办?比如身份证?是否仍建议为 Id 设置 DTO? 不,在这种情况下,对象是标量。但是,特别是对于 id,根据定义,id 标识资源,因此它本身不需要是它自己的资源。【参考方案3】:您可以将多个参数作为 URL 传递,如下例所示
参数名称必须相同(不区分大小写),如果名称不同 匹配则不会设置参数的值。
[HttpPost]
[Route("surveyId/expiryDate")]
public IActionResult Post(int surveyId, DateTime expiryDate)
return Ok(new surveyId, expiryDate );
调用网址
http://localhost:[port]/api/[controller]/1/3-29-2018
【讨论】:
啊,是的,我忘记了这个方法!这不是在正文中发送数据吗? 是的,它只发送您在 URL 中作为参数传递的内容,而不发送表单正文数据 这是 Post/Put 的坏习惯吗?我觉得我以前在某处读过仅对 Get 请求使用 URL 参数? 如果你有敏感数据或者有很多参数不要使用,最好使用带有DTO或模型的post 非常感谢!这对我来说似乎很好用: [HttpPost] [Route("endpoint/id")] public async Task根据上面的答案,我得到了以下代码。希望这对某人有帮助! (当然要感谢其他人让我走上正轨)
/// <summary>
/// Post api/dostuff/id
[HttpPost]
[Route("dostuff/id")]
public async Task<IActionResult> DoStuff([FromBody]Model model, int id)
// Both model and id are available for use!
【讨论】:
感谢您提供这个 - 很高兴知道这是可能的【参考方案5】:你可以用字典来做
Dictionary<int, object> dict = new Dictionary<int, object>();
dict["id"] = 1
dict["date"] = DateTime.Now;
JsonConvert.SerializeObject(dict);
【讨论】:
有趣!为什么是 Dictionary你可以换行
var data = JsonConvert.SerializeObject(id);
与
var data = new StringContent(JsonConvert.SerializeObject((surveyId, expiryDate)), Encoding.UTF8, "application/json");
诀窍是您使用一个 Tuple 对象,其中包含您的参数作为单个参数。
您也应该在服务器端使用 Tuple 类型。它可能看起来像:
[HttpPost]
public Task MyWebApiMethod([FromBody] (int SurveyId, DateTime ExpiryDate) parameters)
int surveyId = parameters.SurveyId;
DateTime expiryDate = parameters.ExpiryDate;
// Process your parameters ...
我现在没有 Visual Studio,如果有任何编译问题等,请见谅。
【讨论】:
以上是关于在 POST API 中传递多个参数,而不使用 .Net Core MVC 中的 DTO 类的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript/jQuery:将多个参数传递给 API 中的 POST 请求
如何使用JSON正文在REST API POST方法中传递多个记录
当我们在ColdFusion中使用API 调用(POST请求)将参数数量传递给服务器时,如何修复“POST请求超出”错误?