0

I have the following controller:

[Route("api/[controller]")]
public class ReleaseController : BaseController
{
    [HttpPut]
    public Task<ReleaseModel> UpdateAsync([FromBody] UpdateReleaseForm form, CancellationToken cancellationToken = default)
        => _releaseService.UpdateAsync(form, cancellationToken);
}

The form among other properties has enum property ReleaseStatus:

public class UpdateReleaseForm
{
    // other props omitted for brevity

    public ReleaseStatus Status { get; set; }
}

I use FluentValidation to create a rule for the Status:

internal sealed class UpdateReleaseFormValidator : AbstractValidator<UpdateReleaseForm>
{
    public UpdateReleaseFormValidator()
    {
        // other rules omitted for brevity

        RuleFor(u => u.Status)
            .ReleaseStatusValidation();
    }
}

public static class RuleBuildersExtensions
{
    public static IRuleBuilderOptions<T, ReleaseStatus> ReleaseStatusValidation<T>(
        this IRuleBuilder<T, ReleaseStatus> rule)
    {
        return rule.
            IsInEnum()
            .WithMessage(
                string.Format("Status should be one of the following values: `{0}`",
                string.Join(", ", Enum.GetNames(typeof(ReleaseStatus)))));
    }
}

The problem is that when a wrong Status passed in to the action method, I get the error:

{
    "errors": {
        "status": [
            "Error converting value \"WrongStatus\" to type '...ReleaseStatus'. Path 'Status', line 4, position 28."
        ]
    },
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "|3405bc61-4f67bebc131b8dc8."
}

I want to get my custom message defined in validation rule instead.

I tried to use NullObjectModelValidator from disable-validation.

Also I tried this:

services.Configure<ApiBehaviorOptions>(options =>
    {
        options.SuppressModelStateInvalidFilter = true;
    });

But get the following:

System.ArgumentNullException: Cannot pass null model to Validate. (Parameter 'instanceToValidate')

Vy Do
  • 46,709
  • 59
  • 215
  • 313
Dmitry Stepanov
  • 2,776
  • 8
  • 29
  • 45
  • 1
    This isn't really model validation: it's `System.Text.Json` and its [`JsonStringEnumConverter`](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonstringenumconverter) type. It isn't able to parse `WrongStatus` into the `Status` property, so the whole JSON parsing process fails. Here's a link to the [source](https://github.com/dotnet/runtime/blob/master/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs#L317-L321). – Kirk Larkin Sep 03 '20 at 11:15

1 Answers1

0

Just an idea, but you could try to make the UpdateReleaseForm form parameter in the UpdateAsync method nullable:

[Route("api/[controller]")]
public class ReleaseController : BaseController
{
    [HttpPut]
    public Task<ReleaseModel> UpdateAsync([FromBody] UpdateReleaseForm? form, CancellationToken cancellationToken = default)
        => _releaseService.UpdateAsync(form, cancellationToken);
}

Maybe that will allow the parameter to be null.

Lennart
  • 752
  • 1
  • 5
  • 18