简体   繁体   中英

FluentValidation validate Enum value

I have the following model:

public class ViewDataItem
{
    public string viewName { get; set; }
    public UpdateIndicator updateIndicator { get; set; }
}

With the following enum:

public enum UpdateIndicator
{
    Original,
    Update,
    Delete
}

And the following Validator:

public class ViewValidator : AbstractValidator<ViewDataItem>
{
    public ViewValidator()
    {
        RuleFor(x => x.viewName).NotEmpty().WithMessage("View name must be specified");
        RuleFor(x => x.updateIndicator).SetValidator(new UpdateIndicatorEnumValidator<UpdateIndicator>());
    }
}

public class UpdateIndicatorEnumValidator<T> : PropertyValidator
{
    public UpdateIndicatorEnumValidator() : base("Invalid update indicator") {}

    protected override bool IsValid(PropertyValidatorContext context)
    {
        UpdateIndicator enumVal = (UpdateIndicator)Enum.Parse(typeof(UpdateIndicator), context.PropertyValue.ToString());

        if (!Enum.IsDefined(typeof(UpdateIndicator), enumVal))
          return false;

        return true;
    }
}

The code is in a WebAPI that receives data via JSON, deserialize it to an object and then validates, but for some reason I can send whatever I please in the updateIndicator , so long as I don't put in an integer value larger than the max index in the enum (ie 1,2 or 3 works fine, but 7 will generate an error).

How can I get this to validate the input of the data I receive to see if that value is actually in the Enum?

Try the built-in IsInEnum()

RuleFor(x => x.updateIndicator).IsInEnum();

This checks if the provided enum value is within the range of your enum, if not, the validation will fail:

"'updateIndicator' has a range of values which does not include '7'."

The problem arises from the fact that the API model builder will convert what is sent to an enum. If a value isn't found, it doesn't populate it, and the default value is used (as it would be with any other property data type that isn't populated).

In order to easily tell if the value sent is a valid enum value, you should make your property nullable. That way, if a value isn't able to be parsed, it will be set to null . If you want to ensure that the property is set, just have your validator not allow null values for it.

public class ViewDataItem
{
    public string viewName { get; set; }
    public UpdateIndicator? updateIndicator { get; set; }
}

public class ViewValidator : AbstractValidator<ViewDataItem>
{
    public ViewValidator()
    {
        RuleFor(x => x.viewName).NotEmpty().WithMessage("View name must be specified");
        RuleFor(x => x.updateIndicator).NotNull();
    }
}

Without setting the property to null, your model will always have a valid value when you have it. Alternatively, you could have the first value of your enum be a dummy value, but that would be a code smell. A null model property makes far more sense.

If you want to find out what the actual value that was sent to the API endpoint was, you'll need to look at creating an HTTP Handler , which is beyond the scope of this question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM