In my ASP.NET Core Web API, when I call a method that is a HttpPost
and receives a DTO object in FromBody
, and sends extra fields that are not in SourceUrlDto
, I fail during binding on the code side.
How can I access this data on name of basicDto
?
public class SourceUrlDto
{
public string SourceApiUrl { get; set; }
public string SourceApiMethodType { get; set; }
public string AuthenticationType { get; set; }
}
public class BasicSourceUrlDto : SourceUrlDto
{
public string Username { get; set; }
public string Password { get; set; }
}
[HttpPost]
[Route("GetUrlData")]
public async Task<IActionResult> GetUrlData([FromBody] SourceUrlDto sourceUrlDto)
{
if (sourceUrlDto is BasicSourceUrlDto basicDto)
{
// ...
}
return Ok();
}
2
Answers
Change your getUrlData method signature to the below:
Then you can access additional params like below:
Call it via from your client like below:
Your request has been failed because, the
sourceUrlDto
parameter is explicitly typed asSourceUrlDto
, so the model binder will only look for properties defined inSourceUrlDto
.Another reason is that,
JSON
properties likeUsername
andPassword
are ignored during model binding because they are not part ofSourceUrlDto
.Also, the cast
sourceUrlDto is BasicSourceUrlDto
will always fail because the binder doesn’t create an instance ofBasicSourceUrlDto
even if the JSON contains fields for Username and Password.In order to fix that, you either can use custom model binder or manually map the model using reflection.
Depending on your scenario, I would personally prefer manual dictionary map of DTO. You can use reflection. Below is a simple example using reflection to manually map properties.
First of all, I would use
Dictionary<string, object> json
as[FromBody]
request parameter.After that, I would map the
SourceUrlDto
from the json I would recieve from request.Finally, would extract the value using reflaction.
Let’s have a look in pactice:
Output:
Note: Keep in mind, this one of the approach using dictionary and reflaction considering your scenario. You could also try using custom model binder. However, it depends on programmer preference and sense of data structure.