by Joakim

Validation of required checkbox in Asp.Net MVC

Why would you want to have a required checkbox, i.e. a checkbox that user would have to check? Well, a typical example would be that you have some sort of terms associated with submitting a form that the user has to agree to.

You might think that decorating a boolean property on one of your MVC models with a RequiredAttribute, would mean that if you presented that property in your view as a checkbox, that would require the user to click that checkbox before submitting the form. This is not the case however. If you take a look at the implementation of the RequiredAttribute it is actually casting the value to validate into a string and checking the string length. If it can’t cast the value to a string, it will just return true for IsValid.

It is quite easy however to create your own custom validation attribute that you could decorate your boolean property with. The following code checks if the decorated property is a bool, and if so, requires it to have been set to true;

public class BooleanRequiredAttribute : ValidationAttribute, IClientValidatable
{
    public override bool IsValid(object value)
    {
        if (value is bool)
            return (bool)value;
        else
            return true;
    }

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

 
Notice the GetClientValidationRules-method above where we specify the error message to display if client-side validation fails, and what the validation type is. The value we provide as the validation type will be rendered as the name of the rule in the HTML element, and will be used further down to tell jQuery how to validate this property.

After creating the new validation attribute, we need to apply it to a boolean property on out model;

[BooleanRequired(ErrorMessage = "You must accept the terms and conditions.")]
[Display(Name = "I accept the terms and conditions")]
public bool TermsAndConditionsAccepted { get; set; }

 
Next, create a simple view with a form that includes you boolean property;

@model MyModel@using (Html.BeginForm())
{
    <fieldset>
        <legend>Terms and Conditions</legend>
        @Html.ValidationSummary(true, "Please correct the errors and try again.")
        <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit.
            Fusce facilisis ullamcorper consequat. Vestibulum non sapien lectus.
            Nullam at quam eu sapien mattis ultrices.
        </p>
        <ol>
            <li>
                @Html.CheckBoxFor(m => m.TermsAndConditionsAccepted)
                @Html.LabelFor(m => m.TermsAndConditionsAccepted, new { @class = "checkbox" })
                @Html.ValidationMessageFor(m => m.TermsAndConditionsAccepted)
            </li>
        </ol>
        <input type="submit" value="Submit" />
    </fieldset>
}

 
Lastly, in order for client-side validation to work, you need to include the following script in your view (or you can just put line 3 in a javascript file that you reference);

<script type="text/javascript">
    (function ($) {
        $.validator.unobtrusive.adapters.addBool("booleanrequired", "required");
    } (jQuery));
</script>

 
This just registers a new validation adapter for the boolean required attribute, where the first parameter is the adapter name and the second parameter is the name of jQuery validate rule. The adapter name should match the value we specified earlier as the validation type, and the jQuery validation required-rule will require the user to check the checkbox.

That’s it! This will make sure that the checkbox is checked by the user client-side (using jQuery unobtrusive validation*) and that the boolean property is set to true server-side when the form is submitted to the server.

*The ClientValidationEnabled and UnobtrusiveJavaScriptEnabled application settings must be set to true in your web.config for client-side validation to work.

  • Max

    Elegant an Working! solution. Thanks!

  • Peter

    Wow, exactly what I was looking for. Nice work.

  • http://www.gambunny.com Ang Yi Yang

    Where would you normally place your custom validation attribute? in a folder named “Attribute”?

    • Fred .

      Folders are always pluralized. Controllers, Models, Views, Filters, Attributes.

  • http://www.degree.no Joakim

    @Ang: It’s a good idea to keep your attributes in a shared folder, what you call this folder is entirely up to you. There isn’t one correct answer to this question. In the project I’m currently working on we have a separate class project in our solution for infrastructure stuff like this, under which I have stored my attributes in “ComponentModel/DataAnnotations” to get a namespace that is similar to that of the default system attributes (like the RegularExpressionAttribute for example, whose namespace is “System.ComponentModel.DataAnnotations”).

  • Daniel Silver

    I like this solution and have used it or something similar, but what if there were multiple terms and each required a separate checkbox to be checked. Where for instance, depending on market requirements the check box list is being generated dynamically and each requires the same type of validation discussed above. I’ve tried multiple ways but haven’t found a good solution that allowed for using an attribute along with a multiple checkbox scenario. Any suggestions…

  • http://www.degree.no Joakim

    @Daniel: Well, I guess that depends on what your model looks like. But from what you stated I would guess that you would have some kind of list that you add Condition/Term objects to? If so it should only be a matter of iterating over this list in your view. So maybe something like this (totally untested code);

    public class Condition
    {
    public string ConditionText { get; set; }
    [BooleanRequired(ErrorMessage = "Condition must be accepted.")]
    [Display(Name = "I accept this condition")]
    public bool ConditionAccepted { get; set; }
    }


    @model IEnumerable<Condition>
    @foreach (var condition in Model)
    {
    <div>@condition.ConditionText</div>
    <div>
    @Html.CheckBoxFor(model => condition.ConditionAccepted)
    @Html.LabelFor(model => condition.ConditionAccepted, new { @class = "checkbox" })
    @Html.ValidationMessageFor(model => condition.ConditionAccepted)
    </div>
    }

  • Devaraju

    In my ASP.NET MVC project I need to write code to check for users whether they accept terms and condition. I am using Entity framework and Database first approach. I have Table called Appterms, in which I have field called TermsAccepted and Date. I also have other fields in Appterms table such as GatewayUserId and termId. ‘ GatewayUserID has ID of registered users and termId is primary key. ‘Termsaccepted’ field is of bit type.
    My condition is:
    by default all the values of ‘Termsaccepted’ fields in Appterms table should return 0 in my database table.

    In my default page, when user clicks on App image, say for example
    appImage.jpg, i should show them ‘Termscondition’ page where they should click on Accept ‘Terms and condition’. When user accept terms, value in ‘Termsaccepted’ field in ‘Appterms’ table should change from 0 to 1 and also it should store current date of when user accepted terms and condition in Date field.

    I tried to follow custom attribute function which is posted in this post MVC 3 How can I make a user view a warning/disclaimer screen but not able to implement as per my needs.
    I am using this post Getting current user id to get id of current user. So after this how can i return 0 or 1 to check they accepted terms and condition.
    Any help?? Thanks..

  • Jb

    This is the best and working solution for MVC 4.

  • http://www.oaklanesolutions.com Angela

    Thank you so much! This worked when other solutions I found did not.

  • http://www.nowebsitea10.com/60n35.html/ barton2535

    Hey there! Rapid question that’s thoroughly away from area.
    Are you aware of how to make simple a website mobile phone welcoming? My webpage appearances weird when surfing around from my mobile phone.
    I’m trying to find a topic or plug-in that could possibly clear up this concern. If you have any suggestions, please share.
    Thanks a lot.

    • Fred .

      Bootstrap is a responsive CSS framework.

  • Anonymous

    in GetClientValidationRules method , this statement ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()), should be replaced by “ErrorMessage=This.ErrorMessage”