Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manually enable jQuery validation with ASP.NET MVC

I'm struggling to understand some of the basics of jQuery validation as wired up with ASP.NET MVC.

The short version of this question is: What magic am I missing that allows the code produced by @Html.EditorFor() to perform jQuery validation, but doesn't work I try to wire up my own jQuery validation using the exact same HTML?

As a learning exercise (and because it mimics what I really want to do in my website) I created a new MVC 4 app in Visual Studio 2012. I added a view model:

using System.ComponentModel.DataAnnotations;
namespace ValidationTest.Models
{
    public class MyViewModel
    {
        [Required]
        public string MyStringValue { get; set; }
    }
}

and I modified Views\Home\Index.cshtml to create a form based on my view model like this:

@model ValidationTest.Models.MyViewModel
@using (Html.BeginForm(new { id = "MyForm" })) {
    @Html.LabelFor(m => m.MyStringValue)
    @Html.EditorFor(m => m.MyStringValue)
    @Html.ValidationMessageFor(m => m.MyStringValue)

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

Finally, I modified the Home controller to supply the view model to the form and to handle the associated POST, like this:

using System.Web;
using System.Web.Mvc;
using ValidationTest.Models;

namespace ValidationTest.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            var viewModel = new MyViewModel();
            return View(viewModel);
        }

        [HttpPost]
        public ActionResult Index(MyViewModel viewModel)
        {
            if (!ModelState.IsValid) return View(viewModel);

            return RedirectToAction("About");
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your app description page.";
            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";
            return View();
        }
    }
}

When I run the project, the web page displays a text box and magically validates that the user must enter a value. So far so good...

Now, my actual app is an online survey. It displays questions and solicits answers based on a script. My actual viewmodel contains properties that map to the text of the question, the value supplied by the user, etc. The viewmodel also contains a Boolean Required property that specifies whether or not the user must supply a value (i.e., whether or not to enable "required" validation in the View) - so this means that I need to remove the [Required] attribute on the MyStringValue property in my viewmodel and supply my own validation magic based on the Required property in the viewmodel.

This is where I get lost. In IE, I can see that the @html.xxx calls in the sample app (outlined above) produces this HTML for the form:

<label for="MyStringValue">MyStringValue</label>
<input  class="text-box single-line" 
        data-val="true" 
        data-val-required="The MyStringValue field is required." 
        id="MyStringValue" 
        name="MyStringValue" 
        type="text" 
        value="" />
<span data-valmsg-for="MyStringValue" data-valmsg-replace="true"></span>

But I don't see any HTML elsewhere on the page that obviously references the jQuery-validation library, nor do I see the JavaScript code that enables validation, so I don't understand why this works at all.

Furthermore, if I remove the [Required] attribute, and hard-code the View to emit the above HTML (without the magic @html.xxx() calls) then no validation happens at all.

What am I missing?

like image 636
Bob.at.Indigo.Health Avatar asked Feb 23 '13 21:02

Bob.at.Indigo.Health


People also ask

How we can use jQuery validation plugin in MVC?

The jQuery validation plugin leverages a CSS selector like syntax to apply a set of validation rules. You can download the plugin (js) file from jQuery website. The password and confirm password objects are matched by the validation plugin for you and shows the message on the equalTo attribute if they don't match.

How can use client side validation in jQuery MVC?

The above properties are set True by default which means MVC 5 platform ensures that client side validation on form validation is on. For jQuery form validation to work, we set "HtmlHelper. UnobtrusiveJavaScriptEnabled = false;" property false in the register form instead of "web.

How do I make sure client validation is enabled in MVC?

We can enable and disable the client-side validation by setting the values of ClientValidationEnabled & UnobtrusiveJavaScriptEnabled keys true or false. This setting will be applied to application level. For client-side validation, the values of above both the keys must be true.


2 Answers

Yes, I was missing something really fundamental.

The page template (_Layout.cshtml) created for a new MVC 4 project contains this code at the end of the page:

        @Scripts.Render("~/bundles/jquery")
        @RenderSection("scripts", required: false)
    </body>
</html>

That code pulls in the jQuery library (after all of the HTML on the page has been seen by the browser) and then renders an optional "section" that can be supplied by the view. That code does not pull in the jQuery validation library.

ASP.NET MVC validation works without jQuery validation, but all of the validation is done in the server. The careful observer will note that, once warned that a missing string value must be supplied, client-side validation makes the warning go away by simply entering a single character in the offended text box. But without jQuery validation enabled, typing into the text box doesn't dynamically remove the warning.

In order to "turn on" jQuery validation for a single view, this code needs to reside somewhere in the view's cshtml file (stylistically, it wants to be at the end of the file since it will show up at the end of the HTML):

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

So, the short answer to my question is to add the above code at the end of my Views\Home\Index.cshtml file. This enables jQuery validation, magic happens, and the data-xxx attributes are no longer ignored. Life is good.

like image 139
Bob.at.Indigo.Health Avatar answered Sep 19 '22 19:09

Bob.at.Indigo.Health


There is no magic that you are missing. The Microsoft 'unobtrusive validation' script can be used in any website that uses jquery and jquery validate. It is not tied to ASP.NET - as long as the HTML is the format that the unobtrusive script expects, then the script will work. This fiddle shows the unobtrusive script applied to a form not produced by ASP.NET.

The unobtrusive script has two main tasks:

  1. Initialize the jquery.validate.js plugin
  2. Read the data-val* attributes in the markup and translate this into jquery validate rules

As you may have read, the markup attributes that the unobtrusive script reads are as follows

data-val="true"
data-val-rulename="message"
data-val-rulename-paramname1="paramvalue"
data-val-rulename-paramname2="paramvalue"

so a input field might look like this

  <input
     data-val="true" 
     data-val-required="This field is required..." 
     data-val-number="Please enter a number..."
     data-val-range="Must be between 50 and 100...",
     data-val-range-min="50"
     data-val-range-max="100"
     id="mynumber" 
     name="mynumber" 
     type="text" value="" />

My personal opinion of the unobtrusive script is that it falls into the category of what Steve Sanderson calls 'demoware' in his MVC book. It does some nice stuff out of the box but it hobbles jquery validate which is much easier to use on its own. I tend to delete it when I start a new project.

like image 23
Dr Blowhard Avatar answered Sep 18 '22 19:09

Dr Blowhard