本文介绍了在ASP.NET核心API中干净地实现ProblemDetails的最佳方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我需要使用ProblemDetails表示验证错误。它的工作情况和预期的一样。但这里有一个很大的问题,我必须在所有操作方法中编写类似的代码,我认为这不是一个好主意。
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
推荐答案
我可以通过使用Startup.cs的ConfigureServices
方法中的以下代码来解决此问题。
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest).ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = c =>
{
ProblemDetails problemDetails = new ProblemDetails();
problemDetails.Status = StatusCodes.Status400BadRequest;
problemDetails.Title = "One or more validation errors occurred.";
problemDetails.Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1";
List<FieldCodeMessage> codeMessages = new List<FieldCodeMessage>();
foreach (var modelState in c.ModelState)
{
if (modelState.Value.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
string[] errorMessageCode = modelState.Value.Errors.Select(a => a.ErrorMessage).FirstOrDefault().Split(':');
string code = errorMessageCode[0];
string message = errorMessageCode[1];
codeMessages.Add(new FieldCodeMessage(field: modelState.Key, code: code, message: message));
}
}
problemDetails.Extensions.Add("Invalid Fields", codeMessages);
return new BadRequestObjectResult(problemDetails);
};
});
我必须使用一个技巧通过使用扩展ValidationAttribute
的IsValid
方法中的:
分隔符将错误代码与消息一起传递。
return new ValidationResult("01:Proprty 1");
如果有人有更好的方法或建议,请添加评论。我很乐意知道。
这篇关于在ASP.NET核心API中干净地实现ProblemDetails的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!