I need custom message for my request.
Currently I am passing below request json from postman
{
"countryid": "14sdsads02"
}
but my model is
public class model
{
public int countryid {get;set;}
}
When pass request from postman, I am getting below error
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|21793cf-495c68ddbc92ab35.",
"errors": {
"$.countryid": [
"The JSON value could not be converted to System.Int32. Path: $.countryid | LineNumber: 1 | BytePositionInLine: 29."
]
}
}
But instead of this, I need custom error in my web api. How can I achieve this?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
If you want to define a custom response in case of 400 then you can do the followings:
The handler
In order to catch the model binding errors you have to wire up a handler for the ApiBehaviorOptions‘s InvalidModelStateResponseFactory (1).
The required delegate is quite generic: Func<ActionContext, IActionResult>. So, first let’s create an interface for this:
public interface IModelBindingErrorHandler
{
IActionResult HandleInvalidModelState(ActionContext context);
}
Here is a simple handler implementation:
public class ModelBindingErrorHandler : IModelBindingErrorHandler
{
private ICorrelationContextAccessor correlationContextAccessor;
private ILogger logger;
public ModelBindingErrorHandler(ICorrelationContextAccessor correlationContextAccessor, ILogger logger)
{
this.correlationContextAccessor = correlationContextAccessor;
this.logger = logger;
}
public IActionResult HandleInvalidModelState(ActionContext context)
{
string correlationId = correlationContextAccessor.CorrelationContext?.CorrelationId;
var modelErrors = context.ModelState
.Where(stateEntry => stateEntry.Value.Errors.Any())
.Select(stateEntry => new InvalidData
{
FieldName = stateEntry.Key,
Errors = stateEntry.Value.Errors.Select(error => error.ErrorMessage).ToArray()
});
logger.LogError("The request contained malformed input.", modelErrors);
var responseBody = new GlobalErrorModel
{
ErrorMessage = "Sorry, the request contains invalid data. Please revise.",
ErrorTracingId = correlationId
};
return new BadRequestObjectResult(responseBody);
}
}
The helper classes
public class GlobalErrorModel
{
public string ErrorMessage { get; set; }
public string ErrorTracingId { get; set; }
}
public class InvalidData
{
public string FieldName { get; set; }
public string[] Errors { get; set; }
public override string ToString() => $"{FieldName}: {string.Join("; ", Errors)}";
}
Self-registration
public static class ModelBindingErrorHandlerRegister
{
/// <summary>
/// This method should be called after <b>AddControllers();</b> call.
/// </summary>
public static IServiceCollection AddModelBinderErrorHandler(this IServiceCollection services)
{
return AddModelBinderErrorHandler<ModelBindingErrorHandler>(services);
}
/// <summary>
/// This method can be used to register a custom Model binder's error handler.
/// </summary>
/// <typeparam name="TImpl">A custom implementation of <see cref="IModelBindingErrorHandler"/></typeparam>
public static IServiceCollection AddModelBinderErrorHandler<TImpl>(this IServiceCollection services)
where TImpl : class, IModelBindingErrorHandler
{
services.AddSingleton<IModelBindingErrorHandler, TImpl>();
var serviceProvider = services.BuildServiceProvider();
var handler = serviceProvider.GetService<IModelBindingErrorHandler>();
services.PostConfigure((ApiBehaviorOptions options) =>
options.InvalidModelStateResponseFactory = handler.HandleInvalidModelState);
return services;
}
}
Usage
public partial class Startup
{
private readonly IConfiguration Configuration;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson();
//Omited for brevity
services.AddModelBinderErrorHandler();
}
//Omited for brevity
}
Method 2
A simple solution is to change type of countryid from int to string in your model”
public class model
{
public string countryid {get;set;}
}
Then in your controller check if the value is convertible to int or not. If not, return a customized BadRequest response:
int countryid;
if (!int.TryParse(model.countryid, out countryid))
return BadRequest("Your customized error message");
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0