.Net Core webApi Adding properties at runtime to an incoming Dto

819 Views Asked by At

I have a situation where I have a core webApi endpoint. I would like to be able to serialize the incoming Json to a Dto. The Dto would contain the necessary fields, but the incoming request may contain additional properties (different for some clients). I need to be able to capture the additional properties as well, but they will only be known at runtime (the records are to be stored in a DocumentDB (Mongo)). I was deserializing to a dynamic object:

[Route("api/Chapter/CreateNewChapter")]
[HttpPost]
public IActionResult CreateNewChapter([FromBody]dynamic incomingJson) 
{
    dynamic incomingObject = JsonConvert.DeserializeObject<ExpandoObject>(incomingJson.ToString(), new ExpandoObjectConverter());
    if (!IsAuthenticated(incomingObject))
        return Unauthorized();
    var createNewChapter = new CreateNewChapter();

    var outgoingJson = createNewChapter.Process(incomingObject);
    var resultJson = JsonConvert.SerializeObject(outgoingJson, Formatting.Indented);
    return Ok(resultJson);   
}

This worked just fine, the problem is that there is no schema or concrete object to use for Swagger, as well as validation on all of the fields was a nightmare.

So ultimately I would like to do something like this:

public class ChapterDto
{
    public int ChapterId {get; set};
    public string ChapterName {get; set};
)

Then if there are additional properties sent in the request (Json), The properties can be added dynamically at runtime. In addition, I would be adding metadata properties "ParentChapterId" etc.

Should I try to map the incoming json to the dto so I know we have the valid incoming properties, then if that passes map the entire Json object to the dynamic object like I'm doing above? Or is there a better way to achieve this?

1

There are 1 best solutions below

0
On

You can use JSON extension data. When deserializing, it will map additional properties not found in the DTO to a suitably-attributed dictionary property that you add to the DTO.

Example usage:

public class ChapterDto
{
    public int ChapterId { get; set; }

    public string ChapterName { get; set; }

    [JsonExtensionData]
    public IDictionary<string, JToken> AdditionalData { get; set; }
}