'Post Multiple Parameters Without DTO Class
I have an action on my web project which calls to an 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);
}
}
In the API project this is received as follows:
[HttpPut]
public IActionResult ExpireSurvey([FromBody] int surveyId)
{
_repository.ExpireSurvey(surveyId, expiryDate);
return Ok();
}
This works fine - however, say I want to pass in an int id and a DateTime variable, how do I serialise and pass them both into the HttpContent? I can do it with a DTO object, but I don't want to be setting up DTO objects when there is only two fields.
Solution 1:[1]
I think it would be helpful to recognize that ASP.NET Core is REST-based and REST fundamentally deals with the concept of resources. While not an unbreakable rule, the general idea is that you should have what you're calling DTOs here. In other words, you're not posting distinct and unrelated bits of data, but an object that represents something.
This becomes increasingly important if you start mixing in things like Swagger to generate documentation for your API. The objects you create become part of that documentation, giving consumers of your API a template for follow in the development of their apps.
Long and short, I'd say embrace the concept of resources/objects/DTOs/whatever. Model the data your API works with. It will help both you as a developer of the API and any consumers of your API.
Solution 2:[2]
You can pass multiple parameters in as URL as below example
Parameter name must be the same (case-insensitive), If names do not match then values of the parameters will not be set.
[HttpPost]
[Route("{surveyId}/{expiryDate}")]
public IActionResult Post(int surveyId, DateTime expiryDate)
{
return Ok(new { surveyId, expiryDate });
}
Call URL
http://localhost:[port]/api/[controller]/1/3-29-2018
Solution 3:[3]
Based on the answers above, I got the following code working. Hope this helps someone! (thanks to others of course for getting me on the right track)
/// <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!
}
Solution 4:[4]
you can do it with a dictionary
Dictionary<int, object> dict = new Dictionary<int, object>();
dict["id"] = 1
dict["date"] = DateTime.Now;
JsonConvert.SerializeObject(dict);
Solution 5:[5]
You can replace the line
var data = JsonConvert.SerializeObject(id);
with
var data = new StringContent(JsonConvert.SerializeObject((surveyId, expiryDate)), Encoding.UTF8, "application/json");
The trick is that you use a Tuple object containig your parameters as a single parameter.
You should use the Tuple type on the the server side as well. It could look like:
[HttpPost]
public Task MyWebApiMethod([FromBody] (int SurveyId, DateTime ExpiryDate) parameters)
{
int surveyId = parameters.SurveyId;
DateTime expiryDate = parameters.ExpiryDate;
// Process your parameters ...
}
I do not have Visual Studio now and sorry if there are any compilation issues etc.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Chris Pratt |
| Solution 2 | |
| Solution 3 | Ross |
| Solution 4 | Richard Lalancette |
| Solution 5 | Mustafa ÖZÇETiN |
