1
votes

Newbie to MVC3 and jquery unobtrusive validation. I am trying to achieve a very simple custom string validation for my mvc view model property. I know there is an existing "Required" attribute but wanted to play with my custom for testing purpose.

Here is my custom validator class:

public class StringRequiredAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        string valueToValidate = value.ToString();

        if ((value == null ) || (valueToValidate.IsEmpty()))
        {
            return false;
        }

        return true;
    }

    public override string FormatErrorMessage(string name)
    {
        return "formatting my custom message here...";
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "stringrequired"
        };

        yield return rule;
    }
}

Here is the view model class property declaration:

[Display(Name = "Custom Property")]
[StringRequired(ErrorMessage="My custom error message goes here")]
public string MyProperty { get; set; }

Here is my script:

jQuery.validator.unobtrusive.adapters.add('stringrequired', [], function (options) {
    options.rules['stringrequired'] = true;
    options.messages['stringrequired'] = options.message;
}
);

jQuery.validator.addMethod('stringrequired', function (value, element, params) {
    //problem is this method is never fired
    if (value == undefined || value == null)
       return false;

    if (value.toString().length == 0)
       return false;

    return true;
},'');

This is my html markup:

<textarea cols="20" data-val="true" data-val-stringrequired="My custom message is
 displayed here" id="MyProperty" name="MyProperty" rows="2">
</textarea>

I have ClientValidationEnabled & UnobtrusiveJavaScriptEnabled set to "true" in web.config

For some reason this is not working. Would appreciate help here. Thank you!

1
What exactly is not working? Error messages? Unhanded exceptions?Jay
@Jay See //problem is this method is never firedAaronLS
Try rendering the tag with @Html.TextAreaFor<> and make sure you are loading references to the jQuery unobtrusive library.Jay
Yes the property is rendered as suggested by jay and all necessary libraries are referenced. I'm not sure why the client method is not fired.Mr. Imish
Have you tested other generic Validation attributes to see if they are firing? Remembering it must be inside a form and MVC must be able to detect this formm.t.bennett

1 Answers

1
votes

Thought i'd add my 2 cents.

I created a demo project and litterally copy and pasted your code and it worked for me. (had to change valueToValidate.IsEmpty() to String.IsNullOrEmpty(valueToValidate) however).

The only difference is my view (as you haven't displayed yours):

@model Test.Models.MyClass
@{
    ViewBag.Title = "Home Page";
}
@using (Html.BeginForm("Post", "Home", FormMethod.Post))
{
    @Html.TextAreaFor(x=>x.MyProperty)
    @Html.ValidationMessageFor(x=>x.MyProperty)

    <input type="submit" value="submit" id="Submit" />
}

Making sure I'm referencing: jQuery, jQuery.Validate, jQuery.Validate.Unobtrusive (in this order)

and that your validation javascript above is called after this

Lastly I reiterate because it bugged me for hours:

If you don't have a form around the validation in the same view, MVC won't write the correct validation info into the Response.

There is a way to force this however by creating a dummy FormContext into the ViewContext, basically putting this line at the top of your partial view:

ViewContext.FormContext = new FormContext();

This will trick MVC into pumping out the validation stuff

Reference