So, previously my team used POST requests for everything. I finally won the war in convincing them the use the verbs as intended.
GETs for queries,
POSTs for creates etc.
We have a pretty complex object which we need to send as a GET:
{
"UserId": "1",
"CategoryId": "39",
"StartMillis": 1609459200000,
"EndMillis": 1635724799000,
"GroupByAttributeTypeId": "105",
"SelectedAttributes": [{
"TypeId": "100",
"AttributeIds": [1]
}, {
"TypeId": "105",
"AttributeIds": [6697]
}
]
}
This is easy as a POST, but not so much as a GET. The Action
method that we created looks something like:
[HttpGet]
[Route(AspNet.Mvc.ActionTemplate)]
public IActionResult GetCompletedAudits([FromQuery]CompletedAuditDto payload)
{
return OkResponse(_auditService.GetCompletedAudit(payload));
}
where CompletedAuditDto
is:
public class CompletedAuditDto
{
public int UserId { get; set; }
public string CategoryId { get; set; }
public long StartMillis { get; set; }
public long EndMillis { get; set; }
public string GroupByAttributeTypeId { get; set; }
public IEnumerable<TypeAttributeDto> SelectedAttributes;
}
and TypeAttributeDto
is:
public class TypeAttributeDto
{
public int TypeId;
public IEnumerable<int> AttrIds;
}
And I've tried many different serializations using the qs library.
But the SelectedAttributes
collection always comes up as null.
I turned my logging down to the debug
level and the model binder doesn't even seem to attempt to deserialize that object (no mention of the SelectedAttributes
collection)
[14:35:44 DBG] Attempting to bind parameter 'payload' of type 'WebApp.Payloads.Request.CompletedAuditDto' ... [14:35:44 DBG] Attempting to bind parameter 'payload' of type 'WebApp.Payloads.Request.CompletedAuditDto' using the name '' in request data ... [14:35:44 DBG] Attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.UserId' of type 'System.Int32' using the name 'UserId' in request data ... [14:35:44 DBG] Done attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.UserId' of type 'System.Int32'. [14:35:44 DBG] Attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.CategoryId' of type 'System.String' using the name 'CategoryId' in request data ... [14:35:44 DBG] Done attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.CategoryId' of type 'System.String'. [14:35:44 DBG] Attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.StartMillis' of type 'System.Int64' using the name 'StartMillis' in request data ... [14:35:44 DBG] Done attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.StartMillis' of type 'System.Int64'. [14:35:44 DBG] Attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.EndMillis' of type 'System.Int64' using the name 'EndMillis' in request data ... [14:35:44 DBG] Done attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.EndMillis' of type 'System.Int64'. [14:35:44 DBG] Attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.GroupByAttributeTypeId' of type 'System.String' using the name 'GroupByAttributeTypeId' in request data ... [14:35:44 DBG] Done attempting to bind property 'WebApp.Payloads.Request.CompletedAuditDto.GroupByAttributeTypeId' of type 'System.String'. [14:35:44 DBG] Done attempting to bind parameter 'payload' of type 'WebApp.Payloads.Request.CompletedAuditDto'. [14:35:44 DBG] Done attempting to bind parameter 'payload' of type 'WebApp.Payloads.Request.CompletedAuditDto'.
Any ideas how I can get this serialized into a format which the model-binder would be happy with. This is one of the many things I have attempted:
UserId=1&CategoryId=39&StartMillis=1609459200000&EndMillis=1635724799000&GroupByAttributeTypeId=105&SelectedAttributes[].TypeId=100&SelectedAttributes[].AttributeIds[]=1&SelectedAttributes[].TypeId=105&SelectedAttributes[].AttributeIds[]=6697
CodePudding user response:
Firstly, you need add getter setter in your model like below:
public class CompletedAuditDto
{
public int UserId { get; set; }
public string CategoryId { get; set; }
public long StartMillis { get; set; }
public long EndMillis { get; set; }
public string GroupByAttributeTypeId { get; set; }
public IEnumerable<TypeAttributeDto> SelectedAttributes { get; set; }
}
public class TypeAttributeDto
{
public int TypeId { get; set; }
public IEnumerable<int> AttrIds { get; set; }
}
Then send request like below:
UserId=1&CategoryId=39&StartMillis=1609459200000&EndMillis=1635724799000&GroupByAttributeTypeId=105&SelectedAttributes[0].TypeId=100&SelectedAttributes[0].AttrIds=1&SelectedAttributes[1].TypeId=105&SelectedAttributes[1].AttrIds=6697