开发者

How do I set multiple error messages for different scenarios in a Custom validation attribute?

开发者 https://www.devze.com 2023-01-20 22:46 出处:网络
I\'m just getting to grips with custom validation attributes, and I\'m trying to write a custom validation attirbute which will be placed at class level to validate against multiple properties of my m

I'm just getting to grips with custom validation attributes, and I'm trying to write a custom validation attirbute which will be placed at class level to validate against multiple properties of my model.

I can access all properties on my model, and I want to be able to check for multiple conditions in my IsValid overload, and report on them, having different error messages as follows (simplistic example).

public override bool IsValid(object value)
    {
        var model = (MyObject) value;

        //if this value is set, I don't want to do anything other checks
        if (model.Prop3)
        {
            return true;
        }

        if (model.Prop1 == "blah" && model.Prop2 == 1)
        {
            ErrorMessage = "you can't enter blah if prop 2 equals 1";
            return false;
        }

        if(model.Prop1 == "blah blah" && model.Prop2 == 2)
        {
            ErrorMessage = "you can't enter blah blah if prop 2 equals 2";
            return false;
        }


        return true;
    }

But when I do this I get an exception on the first time ErrorMessage is referenced "Cannot set property more than once.

Now I could split up my custom attribute into multiple cust开发者_C百科om attributes, but hoped there would be a way to do it in one, otherwise, I'll be repeating my "catch all" in each

//if this value is set, I don't want to do anything other checks
        if (model.Prop3)
        {
            return true;
        }

I've had a search already, but couldn't find anything, so apologies if I am missing anything obvious.

thanks in advance!


In MVC4 you can override IsValid to return different messages as the ValidationResult

public class StrongPasswordAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        if (value == null)
            return new ValidationResult("Password is required");

        var val = value.ToString();

        if (!Regex.Match(val, @"^(?=.*[a-z]).{0,}$").Success)
        {
            return new ValidationResult("Password must contain at least one lower case letter");
        }
        if (!Regex.Match(val, @"^(?=.*[A-Z]).{0,}$").Success)
        {
            return new ValidationResult("Password must contain at least one UPPER case letter");
        }
        if (!Regex.Match(val, @"^(?=.*\d).{0,}$").Success)
        {
            return new ValidationResult("Password must contain at least one number");
        }

        return ValidationResult.Success;
    }
}


Interesting question! I can think of two work-arounds to this. So not proper solutions based on what you want but they might help to re-use your code. Cant you create a CustomAttribute abstract class called MyCustomAttribute (or something) that overrides IsValid in the following way:

public override bool IsValid(object value)
{
    var model = (MyObject) value;

    //if this value is set, I don't want to do anything other checks
    if (model.Prop3)
    {
        return true;
    }

    CustomValidate(model);
}

CustomValidate(MyObject model) is your abstract method then, you can write multiple custom attribute classes that extend MyCustomAttribute and purely need to implement the validation logic for A particular scenario.

So you can have two classes:

public class BlahCustomAttribute : MyCustomAttribute
{
    public override Boolean CustomValidate(MyObject obj)
    {
        if (model.Prop1 == "blah" && model.Prop2 == 1)
        {
            ErrorMessage = "you can't enter blah if prop 2 equals 1";
            return false;
        }
    }
}

public class BlahBlahCustomAttribute : MyCustomAttribute
{
    public override Boolean CustomValidate(MyObject obj)
    {
        if (model.Prop1 == "blah" && model.Prop2 == 1)
        {
            ErrorMessage = "you can't enter blah blah if prop 2 equals 1";
            return false;
        }
    }
}

Hope this helps - not exactly what you wanted but will do the job and its clean as well.

The other solution is to comma-separate the error messages in the ErrorMessage property and handle it in the front-end (but I would go with the first approach).

0

精彩评论

暂无评论...
验证码 换一张
取 消