MVC3: make checkbox required via jQuery validate?

Solution 1:

I've summarized here the correctly-working source code, which resulted from applying the accepted answer. Hope you find it useful.

RequiredCheckbox.aspx

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<RegistrationViewModel>" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>RequiredCheckbox</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script>
    <script src="//ajax.microsoft.com/ajax/jQuery.Validate/1.7/jQuery.Validate.js" type="text/javascript"></script>
    <script src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.js" type="text/javascript"></script>
    <script type="text/javascript" language="javascript">
        $.validator.unobtrusive.adapters.addBool("mandatory", "required");
    </script>
</head>
<body>
    <div>
        <% 
        // These directives can occur in web.config instead
        Html.EnableUnobtrusiveJavaScript();
        Html.EnableClientValidation();
        using (Html.BeginForm())
        { %>
            <%: Html.CheckBoxFor(model => model.IsTermsAccepted)%>
            <%: Html.ValidationMessageFor(model => model.IsTermsAccepted)%>

            <%: Html.TextBoxFor(model => model.ContactName)%>
            <%: Html.ValidationMessageFor(model => model.ContactName)%>
            <button type="submit">Submit</button>
        <% } %>
    </div>
</body>
</html>

RegistrationViewModel.cs

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

public class RegistrationViewModel {
    [Mandatory (ErrorMessage="You must agree to the Terms to register.")]
    [DisplayName("Terms Accepted")]
    public bool isTermsAccepted { get; set; }

    [Required]
    [DisplayName("Contact Name")]
    public string contactName { get; set; }
}

MandatoryAttribute.cs

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

public class MandatoryAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        return (!(value is bool) || (bool)value);
    }
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        ModelClientValidationRule rule = new ModelClientValidationRule();
        rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
        rule.ValidationType = "mandatory";
        yield return rule;
    }
}

Solution 2:

Just change your javascript to this:

(function ($) {
    // http://itmeze.com/2010/12/checkbox-has-to-be-checked-with-unobtrusive-jquery-validation-and-asp-net-mvc-3/
    $.validator.unobtrusive.adapters.add("mandatory", function (options) {
        options.rules["required"] = true;
        if (options.message) {
            options.messages["required"] = options.message;
        }                
    });            
} (jQuery));

You do not actually need to write your own adapter though and can just use:

(function ($) {
    $.validator.unobtrusive.adapters.addBool("mandatory", "required");
} (jQuery));