2
votes

I have an ASP.NET MVC 4 application and I'd like to have unobtrusive validation for several properties of the view model. Here's a simplified version :

ViewModel :

[AtLeastOne(new[] {"FirstName", "LastName"})]
public class PersonViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Validation attribute :

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class AtLeastOneAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string[] _propertyNames;

    public AtLeastOneAttribute(string[] propertyNames)
    {
        if (propertyNames == null) throw new ArgumentNullException("propertyNames");
        if (propertyNames.Length < 2) throw new ArgumentOutOfRangeException("propertyNames");
        _propertyNames = propertyNames;
    }

    public override bool IsValid(object value)
    {
        return true;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var modelClientValidationRule = new ModelClientValidationRule
        {
            ErrorMessage = "AAAAA!!!",
            ValidationType = "atleastone",
        };
        modelClientValidationRule.ValidationParameters.Add(new KeyValuePair<string, object>("propertynames", _propertyNames));
        return new[]
        {
            modelClientValidationRule
        };
    }
}

Although I have :

<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />

in Web.config and

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script type="text/javascript">
        jQuery.validator.unobtrusive.adapters.add("atleastone", ['FirstName', 'LastName'], function (options) {
            alert('options!');
        });
    </script>

set in my view nothing is rendered for this validation. If I, for example, add [Required] for FirstName or LastName, data-* validation attributes are added.

How can I achieve this multi-property custom client-side validation?

WANT TO SEE / DOWNLOAD THE WHOLE SOLUTION?

1
Does your AtLeastOneAttribute has the [AttributeUsage] attribute?haim770
I don't think so. did you register your custom validation method on the client side? something like: jQuery.validator.unobtrusive.add("atleastone")?haim770
I added [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] but nothing is being emitted. I get the feeling that this scenario is not covered..Andrei Rînea
I also added javascript to add an adapter with a dummy function (see update above) and still I get nothing.Andrei Rînea
This guy is saying that this is not possible : stackoverflow.com/a/5803339/1796Andrei Rînea

1 Answers

2
votes

Adding custom validator in the client-side is a 2 step process:

  1. First you need to register your validator (letting the unobtrusive framework knows that such validation exists - but not adding the validation function itself), as you did in jQuery.validator.unobtrusive.adapters.add. you have to remember the function (third parameter) is not the validator, it's only intended for rule configuration (and could be ommited in your case).

  2. Adding the validator itself:

    jQuery.validator.addMethod("atleastone", function (value, element, param) { alert("validating 'atleastone'"); });