我正在Core 3.1和我的一个端点上运行WebAPI,但JSON除外,其模型的字段具有{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|7ced8b82-4aa34d65daa99a12.",
"errors": {
"Vendor.UID": [
"UID is required"
]
}
}
属性,如下所示:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
Common.Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddMvc().AddXmlDataContractSerializerFormatters();
services.AddMvc().AddMvcOptions(options =>
{
options.EnableEndpointRouting = false;
});
services.AddMvcCore(options => options.OutputFormatters.Add(new XmlSerializerOutputFormatter()));
services.AddOptions();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
//Middleware for exception filtering
app.UseMiddleware<ErrorHandlingMiddleware>(new ErrorHandlingMiddlewareOptions { logger = logger });
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseMvc(routes =>
{
routes.MapRoute("EndpointNotFound", "{*url}", new { controller = "Error", action = "EndpointNotFound" });
});
}
}
当我在未设置UID的情况下调用此端点时,将得到预期的以下输出:
{{1}}
虽然此输出非常有用,但显然与我的API通过ExceptionFilter产生的其他错误输出不一致。还有什么办法可以将这些错误发送给异常过滤器?
这是我的Startup.cs:
{{1}}
答案 0 :(得分:1)
为了实现此功能,您需要实现此问题中描述的自己的模型验证器:Model validation in Web API - Exception is thrown with out a throw statement?
答案 1 :(得分:1)
您可以在mvc服务或控制器服务中添加过滤器
此过滤器返回badrequest
services.AddControllers(option =>
{
option.Filters.Add<ValidationFilter>();
});
要创建过滤器,您可以添加此类 您也可以根据需要定制此过滤器
public class ValidationFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
//before contrller
if(!context.ModelState.IsValid)
{
var errorsInModelState = context.ModelState
.Where(x => x.Value.Errors.Count > 0)
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Errors.Select(x => x.ErrorMessage).ToArray());
var errorResponse = new ErrorResponse();
foreach (var error in errorsInModelState)
{
foreach (var subError in error.Value)
{
var errorModel = new ErrorModel
{
FieldName = error.Key,
Message = subError
};
errorResponse.Error.Add(errorModel);
}
context.Result = new BadRequestObjectResult(errorResponse);
return;
}
await next();
//after controller
}
}
}
我已经像这样创建了错误模型
public class ErrorModel
{
public string FieldName { get; set; }
public string Message { get; set; }
}
和如下所示的错误响应
public class ErrorResponse
{
public List<ErrorModel> Error { get; set; } = new List<ErrorModel>();
public bool Successful { get; set; }
}
答案 2 :(得分:0)
您可能想看看很棒的图书馆 FluentValidation!
示例:
构建一个绑定您的 DTO 的验证器模块并创建一组规则。
public class CustomerValidator : AbstractValidator<Customer> {
public CustomerValidator() {
RuleFor(x => x.Surname).NotEmpty();
RuleFor(x => x.Forename).NotEmpty().WithMessage("Please specify a first name");
RuleFor(x => x.Discount).NotEqual(0).When(x => x.HasDiscount);
RuleFor(x => x.Address).Length(20, 250);
RuleFor(x => x.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
}
private bool BeAValidPostcode(string postcode) {
// custom postcode validating logic goes here
}
}
通过 DI 将其注入您的控制器:
services.AddControllers()
.AddFluentValidation(s =>
{
s.ValidatorOptions.CascadeMode = CascadeMode.Stop;
s.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
s.ValidatorOptions.LanguageManager.Culture = new CultureInfo("en-US");
s.RegisterValidatorsFromAssemblyContaining<Customer>();
...
// more validators
});
您可能还想检查为什么在您的控制器上实现 ControllerBase 可能是使用 Web API 时要走的路。
答案 3 :(得分:0)
我刚刚更改了 http 方法并且可以很好地解决相同的问题
[HttpPost("认证")] public IActionResult Authenticate([FromBody]AuthenticateModel 模型)
答案 4 :(得分:0)
您想像这样输出 JSON:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|7ced8b82-4aa34d65daa99a12.",
"errors": {
"Vendor.UID": [
"UID is required"
]
}
}
type
和 status
字段,来自这里 https://github.com/dotnet/aspnetcore/blob/v3.1.17/src/Mvc/Mvc.Core/src/DependencyInjection/ApiBehaviorOptionsSetup.cs#L54-L108,ClientErrorMapping
将在 dotnet 核心项目设置时配置。
JSON 是由 ValidationProblemDetails
、https://github.com/dotnet/aspnetcore/blob/v3.1.17/src/Mvc/Mvc.Core/src/Infrastructure/DefaultProblemDetailsFactory.cs#L45
DefaultProblemDetailsFactory
我们可以使用这个 ProblemDetailsFactory
来创建 ValidationProblemDetails https://github.com/dotnet/aspnetcore/blob/v3.1.17/src/Mvc/Mvc.Core/src/DependencyInjection/MvcCoreServiceCollectionExtensions.cs#L261