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?
-
@PeterCsala . Please under stand i know what is type difference. Only vulnerability purpose i need to stop my property exposing. So how my server level response to customize.value soft– value soft2020年12月12日 11:34:31 +00:00Commented Dec 12, 2020 at 11:34
-
Sorry, I misunderstood your question. I left a solution proposal with the desired behaviour.Peter Csala– Peter Csala2020年12月12日 12:16:17 +00:00Commented Dec 12, 2020 at 12:16
-
What is the format that you want to custom error?For how to custom error message you could refer to:stackoverflow.com/a/62989600/11398810.Rena– Rena2020年12月14日 06:34:26 +00:00Commented Dec 14, 2020 at 6:34
2 Answers 2
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
}
2 Comments
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");
Comments
Explore related questions
See similar questions with these tags.