1

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!

Sparky
  • 98,165
  • 25
  • 199
  • 285
Mr. Imish
  • 84
  • 2
  • 6
  • What exactly is not working? Error messages? Unhanded exceptions? – Jay Jun 19 '13 at 21:10
  • @Jay See `//problem is this method is never fired` – AaronLS Jun 19 '13 at 21:18
  • Try rendering the tag with `@Html.TextAreaFor<>` and make sure you are loading references to the jQuery unobtrusive library. – Jay Jun 19 '13 at 21:22
  • 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 Jun 19 '13 at 21:36
  • 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 form – m.t.bennett Jun 19 '13 at 22:38
  • Yes the other data anno.....validations are firing for the same view and also my other custom validations. – Mr. Imish Jun 19 '13 at 22:44
  • Ill make a demo project and check it out - one thing I mentioned before (and that I've run into) is that I was using a partial view, and the form in the consuming view, and MVC would detect no form and not write the correct data into the request because of it. Also, silly question, but you have got in your view @Html.Validation for MyProperty? – m.t.bennett Jun 19 '13 at 22:47
  • Just created a test MVC3 project, litterally copy and pasted your code and it's working client side for me! Can you show your view? – m.t.bennett Jun 19 '13 at 23:05
  • wow, I've no access to the code now, early tomorrow I should be able to provide more details. You said something about the partial view? Yes it is a partial view rendered inside a form and the same partial view has validation summary. Nonetheless the other data anno....works but not only this. – Mr. Imish Jun 19 '13 at 23:19
  • Is the form inside the partial view? see my answer for my info. Is the form being loaded dynamically after the page in anyway? – m.t.bennett Jun 19 '13 at 23:20
  • No. But let me explain the flow to be more precise. A view called "create" has a html.beginform and a partial view called "_addeditDrug" is rendered inside this form/view. The validation summary, submit button is inside this partial view. Does it make sense. – Mr. Imish Jun 19 '13 at 23:23
  • I know why it is not firing for me. This textarea which i am playing with is converted to html editor and some how jquery ignores that. If i remove the HTML editor code it fires correctly. Somehow i have to figure out how to get that working. I am using jHtmlArea plugin to render the editor – Mr. Imish Jun 20 '13 at 13:44
  • Sorry for the late reply, but could not get this working. i will stop investigating this for now and will revisit after some time. Till now i can leave with server validation which fires off. Thanks all for the help.... – Mr. Imish Jun 21 '13 at 19:47

1 Answers1

1

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

Community
  • 1
  • 1
m.t.bennett
  • 1,290
  • 16
  • 34