【发布时间】:2022-01-03 16:22:48
【问题描述】:
我需要使用ProblemDetails 来处理验证错误。它按预期工作。但是这里有个大问题,我必须在所有的action方法中写一个类似的代码,我认为这不是一个好主意。
public async Task<ActionResult<SampleResponse>> Post([FromBody] SampleRequest getRateApiRequest)
{
try
{
if (ModelState.IsValid == false)
{
ProblemDetails problemDetails = new ProblemDetails();
problemDetails.Detail = "Detail";
problemDetails.Instance = "Instance";
problemDetails.Status = StatusCodes.Status400BadRequest;
problemDetails.Title = "Title";
problemDetails.Type = "Type";
List<FieldCodeMessage> codeMessages = new List<FieldCodeMessage>();
foreach (var modelState in ModelState)
{
if (modelState.Value.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
MemberInfo property = typeof(TradeBookingRequestAPI).GetProperty(modelState.Key);
var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().Single();
string displayName = attribute.DisplayName;
switch (modelState.Key)
{
case "Property1":
codeMessages.Add(new FieldCodeMessage(field: displayName, code: "01", message: modelState.Value.Errors.Select(a => a.ErrorMessage).FirstOrDefault()));
break;
case "Property2":
codeMessages.Add(new FieldCodeMessage(field: displayName, code: "02", message: modelState.Value.Errors.Select(a => a.ErrorMessage).FirstOrDefault()));
break;
case "Property3":
codeMessages.Add(new FieldCodeMessage(field: displayName, code: "03", message: modelState.Value.Errors.Select(a => a.ErrorMessage).FirstOrDefault()));
break;
case "Property4":
codeMessages.Add(new FieldCodeMessage(field: displayName, code: "04", message: modelState.Value.Errors.Select(a => a.ErrorMessage).FirstOrDefault()));
break;
case "Property5":
codeMessages.Add(new FieldCodeMessage(field: displayName, code: "05", message: modelState.Value.Errors.Select(a => a.ErrorMessage).FirstOrDefault()));
break;
case "Property6":
codeMessages.Add(new FieldCodeMessage(field: displayName, code: "06", message: modelState.Value.Errors.Select(a => a.ErrorMessage).FirstOrDefault()));
break;
}
}
}
problemDetails.Extensions.Add("Invalid Fields", codeMessages);
return BadRequest(problemDetails);
}
}
catch (Exception)
{
...
}
}
那么有没有办法在一个集中的地方处理这个问题,比如中间件或其他东西。
预期响应:
{
"type": "Type",
"title": "Title",
"status": 400,
"detail": "Detail",
"instance": "Instance",
"Invalid Fields": [
{
"field": "Proprty 1",
"code": "01",
"message": "Invalid Proprty 1"
},
{
"field": "Property 2",
"code": "02",
"message": "Invalid Property 2"
}
]
}
我已经扩展ValidationAttribute 来实现所有属性的验证逻辑,下面是Property1 的实现。
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
try
{
if (value != null)
{
propertyDisplayName = validationContext.DisplayName;
long property1 = (Int64)value;
Match match = Regex.Match($"{property1}", @"^\d+$", RegexOptions.IgnoreCase);
if (!string.IsNullOrWhiteSpace($"{property1}") && match.Success)
{
return ValidationResult.Success;
}
else
{
return new ValidationResult($"Invalid {propertyDisplayName}");
}
}
else
{
return new ValidationResult($"Invalid {propertyDisplayName}");
}
}
catch (Exception ex)
{
...
}
}
如果在扩展的ValidationAttribute 类中也有处理这种情况的方法,那也适用于我。
注意:目标框架是.Net5
【问题讨论】:
-
嗨@vivek nuna,我想你可以尝试自定义扩展
ValidationProblemDetails的类。参考:stackoverflow.com/a/67916802/11398810 -
@Rena 是的,我尝试过使用类似的解决方法。完成后我会发布。谢谢你的建议。
-
@Rena 我已经添加了我的答案,请查看并提供您的反馈:)
标签: c# asp.net-core asp.net-web-api asp.net-core-webapi .net-5