如何反序列化 422 不可处理的实体错误模型并将错误绑定到 asp.net core razor pages 模型状态
How to deserialize 422 unprocessable entity error model and bind the errors to asp.net core razor pages model state
我的Asp.Net Core 3.1 API
returns422 Unprocessable Entity
错误响应如下图:
{
"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."
]
}
}
如何反序列化此响应并将错误添加到 Asp.Net Core 3.1 Razor Pages
中的模型验证错误?
我尝试创建如下所示的模型,
错误型号:
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
}
但是我应该在Errors
里面添加什么class?错误键和消息将是动态的。
了解以上内容后,我可以在我的剃须刀页面中添加模型状态错误,如下所示,
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
}
首先,您应该确保关键字段名称与从 api(pay attention to case
).
返回的 json 相同
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; }
}
那么Errors
class的字段应该包含验证class的所有字段,并且字段名要一致,但是需要define their type as an array to receive
,因为json中错误返回的每个字段都是一个数组。 (这里我创建了一个简单的验证 class 命名为 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; }
}
然后您可以使用如下代码:
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]);
}
}
我已经修改了@Yongqing Yu 的答案并使其通用。
422错误型号:
public class UnprocessableEntity<T>
{
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("status")]
public int Status { get; set; }
[JsonPropertyName("detail")]
public string Detail { get; set; }
[JsonPropertyName("instance")]
public string Instance { get; set; }
[JsonPropertyName("traceId")]
public string TraceId { get; set; }
[JsonPropertyName("errors")]
public T Errors { get; set; }
}
型号:
public class EventRegisterViewModel
{
[Required]
[MaxLength(200)]
[RegularExpression(ValidationConstants.ALPHABETSWITHSPACE, ErrorMessage = "Enter only alphabets")]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[MaxLength(200)]
[RegularExpression(ValidationConstants.ALPHABETSWITHSPACE, ErrorMessage = "Enter only alphabets")]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[MinLength(10, ErrorMessage = "Please Enter 10 digit Mobile Number")]
[MaxLength(10)]
[RegularExpression(ValidationConstants.NUMBERSONLY, ErrorMessage = "Invalid Mobile Number")]
[Display(Name = "Mobile Number")]
public string MobileNumber { get; set; }
[Required]
[MaxLength(200)]
[EmailAddress]
[Display(Name = "Email Address")]
public string EmailAddress { get; set; }
}
错误型号:
public class EventRegistrationValidationErrors
{
public IEnumerable<string> FirstName { get; set; }
public IEnumerable<string> LastName { get; set; }
public IEnumerable<string> MobileNumber { get; set; }
public IEnumerable<string> EmailAddress { get; set; }
}
反序列化时,
using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
var errorResponse = await JsonSerializer.DeserializeAsync<UnprocessableEntity<EventRegistrationValidationErrors>>(responseStream).ConfigureAwait(false);
var errorFieldNames = typeof(EventRegistrationValidationErrors)
.GetProperties()
.Select(field => field.Name)
.ToList();
foreach (var errorField in errorFieldNames)
{
var errorLists = (List<string>)errorResponse.errors
.GetType()
.GetProperty(errorField)
.GetValue(errorResponse.errors);
if (!(errorLists is null))
{
ModelState.AddModelError($"Event.{errorField}", errorLists[0]);
}
}
希望这对外面的人有所帮助。
我的Asp.Net Core 3.1 API
returns422 Unprocessable Entity
错误响应如下图:
{
"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."
]
}
}
如何反序列化此响应并将错误添加到 Asp.Net Core 3.1 Razor Pages
中的模型验证错误?
我尝试创建如下所示的模型,
错误型号:
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
}
但是我应该在Errors
里面添加什么class?错误键和消息将是动态的。
了解以上内容后,我可以在我的剃须刀页面中添加模型状态错误,如下所示,
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
}
首先,您应该确保关键字段名称与从 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; }
}
那么Errors
class的字段应该包含验证class的所有字段,并且字段名要一致,但是需要define their type as an array to receive
,因为json中错误返回的每个字段都是一个数组。 (这里我创建了一个简单的验证 class 命名为 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; }
}
然后您可以使用如下代码:
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]);
}
}
我已经修改了@Yongqing Yu 的答案并使其通用。
422错误型号:
public class UnprocessableEntity<T>
{
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("status")]
public int Status { get; set; }
[JsonPropertyName("detail")]
public string Detail { get; set; }
[JsonPropertyName("instance")]
public string Instance { get; set; }
[JsonPropertyName("traceId")]
public string TraceId { get; set; }
[JsonPropertyName("errors")]
public T Errors { get; set; }
}
型号:
public class EventRegisterViewModel
{
[Required]
[MaxLength(200)]
[RegularExpression(ValidationConstants.ALPHABETSWITHSPACE, ErrorMessage = "Enter only alphabets")]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[MaxLength(200)]
[RegularExpression(ValidationConstants.ALPHABETSWITHSPACE, ErrorMessage = "Enter only alphabets")]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[MinLength(10, ErrorMessage = "Please Enter 10 digit Mobile Number")]
[MaxLength(10)]
[RegularExpression(ValidationConstants.NUMBERSONLY, ErrorMessage = "Invalid Mobile Number")]
[Display(Name = "Mobile Number")]
public string MobileNumber { get; set; }
[Required]
[MaxLength(200)]
[EmailAddress]
[Display(Name = "Email Address")]
public string EmailAddress { get; set; }
}
错误型号:
public class EventRegistrationValidationErrors
{
public IEnumerable<string> FirstName { get; set; }
public IEnumerable<string> LastName { get; set; }
public IEnumerable<string> MobileNumber { get; set; }
public IEnumerable<string> EmailAddress { get; set; }
}
反序列化时,
using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
var errorResponse = await JsonSerializer.DeserializeAsync<UnprocessableEntity<EventRegistrationValidationErrors>>(responseStream).ConfigureAwait(false);
var errorFieldNames = typeof(EventRegistrationValidationErrors)
.GetProperties()
.Select(field => field.Name)
.ToList();
foreach (var errorField in errorFieldNames)
{
var errorLists = (List<string>)errorResponse.errors
.GetType()
.GetProperty(errorField)
.GetValue(errorResponse.errors);
if (!(errorLists is null))
{
ModelState.AddModelError($"Event.{errorField}", errorLists[0]);
}
}
希望这对外面的人有所帮助。