My Asp.Net Core 3.1 API
returns 422 Unprocessable Entity
error response as shown below:
{
"type": "https://test.com/modelvalidationproblem",
"title": "One or more model validation errors occurred.",
"status": 422,
"detail": "See the errors property for details.",
"instance": "/api/path",
"traceId": "8000003f-0001-ec00-b63f-84710c7967bb",
"errors": {
"FirstName": [
"The FirstName field is required."
]
}
}
How to deserialize this response and add the errors to model validation error in Asp.Net Core 3.1 Razor Pages
?
I tried to create model as shown below,
Error Model:
public class UnprocessableEntity
{
public string Type { get; set; }
public string Title { get; set; }
public int Status { get; set; }
public string Detail { get; set; }
public string Instance { get; set; }
public string TraceId { get; set; }
public Errors Errors { get; set; }
}
public class Errors
{
....// what should I need to add here? Keys and messages will be dynamic
}
However what I should add inside Errors
class? The error keys and messages will be dynamic.
Once above things is known, I can add model state errors in my razor pages as shown below,
using var responseStream = await response.Content.ReadAsStreamAsync();
var errorResponse = await JsonSerializer.DeserializeAsync<UnprocessableEntity>(responseStream);
foreach (var error in errorResponse.errors)
{
ModelState.AddModelError(error.key, error.Message[0]); // I'm stuck here
}
First, you should ensure the key field names are the same as the json returned from api(pay attention to case
).
public class UnprocessableEntity
{
public string type { get; set; }
public string tTitle { get; set; }
public int status { get; set; }
public string detail { get; set; }
public string instance { get; set; }
public string traceId { get; set; }
public Errors errors { get; set; }
}
Then, the fields of the Errors
class should contain all the fields of the validated class, and the field names should be consistent, but you need to define their type as an array to receive
, because each field returned by errors in json is an array. (here i created a simple validated class named StudInfo
):
public class StudInfo
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class Errors
{
public List<string> Id { get; set; }
public List<string> Name { get; set; }
}
Then the code you can use as follow:
using var responseStream = await response.Content.ReadAsStreamAsync();
var errorResponse = await JsonSerializer.DeserializeAsync<UnprocessableEntity>(responseStream);
var t = typeof(Errors);
var fieldNames = typeof(Errors).GetProperties()
.Select(field => field.Name)
.ToList();
foreach (var name in fieldNames)
{
List<string> errorLists = (List<string>)errorResponse.errors.GetType().GetProperty(name).GetValue(errorResponse.errors);
if (errorLists != null)
{
ModelState.AddModelError(name, errorLists[0]);
}
}