0

My development environment is.Net7 WebApi (out of the box)

Below is the relevant code. DataAnnotations I have implemented localization.

using System.ComponentModel.DataAnnotations;

namespace WebApi.Dtos
{
    public class UserRegistrationDto
    {
        [Required(ErrorMessage = "UserNameRequiredError")]
        [MinLength(6, ErrorMessage = "UserNameMinLengthError")]
        [MaxLength(30, ErrorMessage = "UserNameMaxLengthError")]
        public required string UserName { get; set; }

        [Required(ErrorMessage = "PasswordRequiredError")]
        public required string Password { get; set; }
    }
}
[HttpPost]
public async Task<IActionResult> RegisterUser([FromBody] UserRegistrationDto userRegistration)
{
    return Ok(1);
    // IdentityResult userResult = await _userManager.CreateAsync(new IdentityUser { UserName = userRegistration.UserName }, userRegistration.Password);

    // return userResult.Succeeded ? StatusCode(201) : BadRequest(userResult);
}

When the request body is invalid JSON.

curl -X 'POST' \
  'https://localhost:7177/Authenticate/RegisterUser' \
  -H 'accept: */*' \
  -H 'Api-Version: 1.0' \
  -H 'Content-Type: application/json' \
  -d '{}'
{
    "$": [
        "JSON deserialization for type 'WebApi.Dtos.UserRegistrationDto' was missing required properties, including the following: userName, password"
    ],
    "userRegistration": [
        "The userRegistration field is required."
    ]
}

When the request body is Empty.

curl -X 'POST' \
  'https://localhost:7177/Authenticate/RegisterUser' \
  -H 'accept: */*' \
  -H 'Api-Version: 1.0' \
  -H 'Content-Type: application/json' \
  -d ''
{
    "": [
        "The userRegistration field is required."
    ]
}

It throws exception information before binding to DTO, can this exception information be localized? If not, is it possible to capture this information for secondary processing, such as returning a fixed JSON format?

I've tried this in the Program.cs entry file, but it's not ideal.

.ConfigureApiBehaviorOptions(options =>
{
    options.SuppressModelStateInvalidFilter = false;
    options.InvalidModelStateResponseFactory = context =>
    {
        bool knownExceptions = context.ModelState.Values.SelectMany(x => x.Errors).Where(x => x.Exception is JsonException || (x.Exception is null && String.IsNullOrWhiteSpace(x.ErrorMessage) == false)).Count() > 0;
        if (knownExceptions)
        {
            return new BadRequestObjectResult(new { state = false, message = localizer["InvalidParameterError"].Value });
        }
        // ...
        return new BadRequestObjectResult(context.ModelState);
    };
})

I have also tried this method, but I can’t capture the exception information that failed when binding DTO alone. They will appear together with the ErrorMessage exception information in DTO like the above writing method.

.AddControllers(options =>
{
    // options.Filters.Add(...);
    // options.ModelBindingMessageProvider // This doesn't work either, it seems to support [FromForm]
})

Back to the topic, can it be localized? Or there is something wrong with the code. I just learned .Net not long ago. Most of the information I learned came from search engines and official documents. Thanks in advance.

Ismaili Mohamedi
  • 906
  • 7
  • 15
Jarvie789
  • 1
  • 3
  • If you wanna localize error message, You can refer to this [issue](https://stackoverflow.com/questions/40828570/asp-net-core-model-binding-error-messages-localization) – Xinran Shen Dec 19 '22 at 08:22
  • @XinranShen I tried ModelBindingMessageProvider, it has no effect. – Jarvie789 Dec 19 '22 at 15:15
  • But in generally, You can use This provider to localize error message, Check this [Blog](https://ziyad.info/en/articles/18-Localizing_ModelBinding_Error_Messages), Is it what you want? It also use the link i provided before. – Xinran Shen Dec 20 '22 at 08:18
  • @XinranShen Yes, I just tried it and it does work. But can the first JSON serialization error be localized? `JSON deserialization for type 'WebApi.Dtos.UserRegistrationDto' was missing required properties, including the following: userName, password` If I set `MaxModelValidationErrors=1` and pass invalid parameters, it always returns the first error. But it doesn't matter much to me right now. I can set the DTO model to be empty in the method of the controller, for example `[FromBody] UserRegistrationDto? userRegistration` – Jarvie789 Dec 20 '22 at 09:14
  • In MVC, You can set javascript validation, If input is null or invalid, It will not be send to the backend. Maybe you can refer to this [Blog](https://dev.to/moesmp/what-every-asp-net-core-web-api-project-needs-part-4-error-message-reusability-and-localization-229i). – Xinran Shen Dec 21 '22 at 03:17
  • 1
    @XinranShen Thank you. I have read these articles before posting the question. Initially, I wanted to unify the format of these exception messages. From my current understanding of .Net, it seems that the exception of JSON deserialization can only be verified on the client side for the time being. I still need to continue to study later, maybe there will be a better way, I plan to close this question, thank you again. – Jarvie789 Dec 21 '22 at 04:15

1 Answers1

0

Use the following method.

.AddControllers(options =>
{
    // options.ModelBindingMessageProvider.Set...
})

It seems that the exception of JSON deserialization caused by passing invalid parameters can only be eliminated on the client side. So far it seems I haven't found a localization for this exception, but it's not very important to me at the moment. Thanks @XinranShen for helping point me in the right direction.

Jarvie789
  • 1
  • 3