How to make "One or more validation errors occurred" raise an exception?
Solution 1
You can add filter in your mvc service or controller service
this filter return badrequest
services.AddControllers(option =>
{
option.Filters.Add<ValidationFilter>();
});
to create your filter you can add this class also you can customize this filter to what ever you want
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
}
}
}
I have created error model just like this
public class ErrorModel
{
public string FieldName { get; set; }
public string Message { get; set; }
}
and error response like below
public class ErrorResponse
{
public List<ErrorModel> Error { get; set; } = new List<ErrorModel>();
public bool Successful { get; set; }
}
Solution 2
In order to achive this functionality you need to implement your own model validator described in this question: Model validation in Web API - Exception is thrown with out a throw statement?
AnKing
Updated on June 21, 2022Comments
-
AnKing over 1 year
I'm running a WebAPI on Core 3.1 and one of my endpoints excepts JSON with a model that has fields with
[Required]
attribute like so:public class Vendor { public int ID { get; set; } [Required(ErrorMessage = "UID is required")] <<<------ required attribute public string UID { get; set; } }
When i call this endpoint without setting UID I get the following output as expected:
{ "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" ] } }
Altho this output is pretty informative and clear it is not consistent with other error outputs that my API produces by means of ExceptionFilter. Is there any way this errors can be routed to the exception filter as well?
Here is my Startup.cs:
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" }); }); } }