8

I try to apply back end validation whenever empty or invalid values are send to ASP.NET Core Web API endpoint, but I can't figure out how to handle model binding failure errors.

Getting this error probably from ModelState when submitting invalid values: totalPrice: ["Could not convert string to decimal: . Path 'totalPrice', line 1, position 71."] 0: "Could not convert string to decimal: . Path 'totalPrice', line 1, position 71." It looks like model binding is failing and error is displayed directly to the client.

I have pretty simple controller decorated with ApiController attribute.

[ApiController]
public class ProductsController
{
    [HttpPost]
    public IActionResult Post([FromBody]CreateProductDto model)
    {    
        model.Id = await service.CreateProduct(model);

        return CreatedAtRoute(
            routeName: "GetProduct", 
            routeValues: new { id = model.Id }, 
            value: model
        );
    }
}

and my DTO model

public class CreateProductDto
{
    [Required(ErrorMessage = "Invalid value")]
    public decimal totalPrice { get; set;}

    public int count { get; set; }
}

Is there a way to customize the text from model binding errors? I would like to prevent sensitive info to be send and provide friendly feedback to the client?

2
  • 1
    Yo're getting the error on model binding. You can register global error filter and handle error based on its type. Commented Dec 9, 2018 at 22:52
  • 1
    I recommend a custom model binder. It's a bit more work but gives you far more flexibility. Commented Dec 10, 2018 at 3:32

1 Answer 1

5

You can customize your error message from Startup class in ConfigureServices method. You can see details Microsoft document.

Here is an example -

services.AddMvc(options =>
            {
                var iStrFactory = services.BuildServiceProvider().GetService<IStringLocalizerFactory>();
                var L = iStrFactory.Create("ModelBindingMessages", "WebUI"); // Resource file location 
                options.ModelBindingMessageProvider.SetValueIsInvalidAccessor((x) => L["The value '{0}' is invalid."]);

                options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor((x) => L["The field {0} must be a number."]);
                options.ModelBindingMessageProvider.SetMissingBindRequiredValueAccessor((x) => L["A value for the '{0}' property was not provided.", x]);
                options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor((x, y) => L["The value '{0}' is not valid for {1}.", x, y]);
                options.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(() => L["A value is required."]);
                options.ModelBindingMessageProvider.SetUnknownValueIsInvalidAccessor((x) => L["The supplied value is invalid for {0}.", x]);
                options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor((x) => L["Null value is invalid.", x]);
            });

You can read this blog.

Sign up to request clarification or add additional context in comments.

10 Comments

I really hoped that would do the trick but it doesn't :/ Tried all the possible properties of ModelBindingMessageProviders. It was very elegant way for handling those errors.
You can validate your model using IValidatableObject and you can provide your custom error message also. Give a try this, learn.microsoft.com/en-us/aspnet/core/mvc/models/… and stackoverflow.com/questions/56588900/…
You can have a look on this also stackoverflow.com/questions/3400542/…
Just tried that and debugged it, but it looks like the error is thrown before ValidationContext and it's somewhere from Newtonsoft.JSON serializer when the model gets bind.
@Victor I've created GitHub issue and the ASP.NET team promised to fix that in the next release - 3.0.0-preview. See github.com/aspnet/AspNetCore/issues/12472
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.