-
Notifications
You must be signed in to change notification settings - Fork 25.2k
How to log automatic 400 responses on model validation errors #12157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
There's a section in the docs that explains how to customise the BadRequest response when using the built-in filter. You can set the @Rick-Anderson I can provide an example of what that would look like here if it would be helpful. Otherwise, is this something that could be taken over to Stack Overflow with a link. What's the best approach for handling something like that? |
@serpent5 an example in this issue would be great. We can add a link to this issue in the doc and close the issue. |
There are a few ways to approach this, but I'll list a couple of ideas to get you started:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
// Get an instance of ILogger (see below) and log accordingly.
return new BadRequestObjectResult(context.ModelState);
};
}); With this option, the response will not be wrapped in
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.PostConfigure<ApiBehaviorOptions>(options =>
{
var builtInFactory = options.InvalidModelStateResponseFactory;
options.InvalidModelStateResponseFactory = context =>
{
// Get an instance of ILogger (see below) and log accordingly.
return builtInFactory(context);
};
}); This option sets up a wrapper function that first performs your custom logging and then invokes the existing factory function. This ensures that the default functionality that comes out-of-the-box will work as it did before, but it might be overkill if you do want to take full control of the response or don't need Getting an instance of
|
@Rick-Anderson Added link to the doc in #12315 per your plan --
|
It seems too complex, I just wanna a log.. |
@RobinHSanner, did you mean “disable the automatic 400 error handling”? We want to enable logging. And we need to log before return, as I asked at the beginning of the thread
|
I want to keep "automatic 40x error handling" and log custom log. |
Yes, that's what I meant. Thank you for the clarification. Sorry I obviously didn't read carefully enough. I feel pretty stupid for suggesting what you said you were having to do. I obviously have to stop skimming and read more carefully. |
I still feel this is complicated to log errors. Probably we need to have something as simple as enabling InvalidModelStateErrors that also logs the details of the request. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@serpent5 Could you please expand your original reply to also include how one can add the "traceId" property to their custom bad request response? EDIT: var problemDetails = new ValidationProblemDetails(context.ModelState)
{
Type = "https://contoso.com/probs/modelvalidation",
Title = "One or more model validation errors occurred.",
Status = StatusCodes.Status400BadRequest,
Detail = "See the errors property for details.",
Instance = context.HttpContext.Request.Path,
Extensions =
{
["traceId"] = Activity.Current?.Id ?? context.HttpContext?.TraceIdentifier
}
}; |
Thanks for the example @spiritbob. I think we can just leave your comment as-is to help others that want to do the same. What do you think? |
@serpent5 I think it is more proper if someone can take all of the relevant information in here and find its place in the docs. I find it odd requiring the end-user to scroll through issues to a given project, which should only be relevant to active developers/contributors of that project. If you'd like, I can attempt to tackle on this in my free time and hopefully make an initial PR we can all iron out? |
Sure, that sounds like a good idea. |
|
I have created a handler to log and return model binding exceptions. The handler gets invoked and logs the error before returning the error response
|
@harafat007 , have you post ChatGPT answer? |
@michael-freidgeim-webjet this is my own code. No chat gpt code |
Thanks @harafat007 for your snippet. Starting from your snippet, I made following changes:
I removed the public static void ConfigureValidationApiBehavior(this IMvcBuilder builder)
{
builder.ConfigureApiBehaviorOptions(options =>
{
var builtInFactory = options.InvalidModelStateResponseFactory;
options.InvalidModelStateResponseFactory = context =>
{
var logger = context.HttpContext.RequestServices.GetService<ILoggerFactory>()?
.CreateLogger("ValidationLogger");
var errorInfo = new Dictionary<string, Collection<string>>(StringComparer.Ordinal);
if (logger == null || context.ModelState.Count == 0)
{
return builtInFactory(context);
}
foreach (var modelState in context.ModelState)
{
if (!errorInfo.TryGetValue(modelState.Key, out Collection<string>? errorMessages))
{
errorMessages = [];
errorInfo.Add(modelState.Key, errorMessages);
}
foreach (var error in modelState.Value.Errors)
{
errorMessages.Add(error.ErrorMessage);
}
}
logger.LogWarning("Validation errors: {@message}", errorInfo);
return builtInFactory(context);
};
});
} Usage: builder.Services.AddControllers().ConfigureValidationApiBehavior(); |
“The ApiController attribute makes model validation errors automatically trigger an HTTP 400 response.”
It is not described, does details of 400 errors logged or not?
If not, is it possible to configure error details to be logged?
Or I have to SuppressModelStateInvalidFilter = true; and do logging by myself in the block
if (!ModelState.IsValid)
{
Log (ModelState);
return BadRequest(ModelState);
}
Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
The text was updated successfully, but these errors were encountered: