1

I have UI where i am showing 3 checkboxes and each refer to different property of model class. i am using jquery unobtrusive validation just by mvc data annotation. i want when user submit form then user has to select one checkbox otherwise client side error message will display and form will not be submitted.

i can do it by jquery but i want to do it by mvc data annotation.

see my model class

public class Customer
{
    [Required]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }

    [Display(Name = "Mail to me")]
    public bool SelfSend { get; set; }

    [Display(Name = "3rd party")]
    public bool thirdParty { get; set; }

    [Display(Name = "Others")]
    public bool Others { get; set; }
}

Controller

[ValidateAntiForgeryToken()]
[HttpPost]
public ActionResult Index(Customer customer)
{
    if (customer.Others == false || customer.SelfSend == false || customer.thirdParty == false)
        ModelState.AddModelError("Error", "Must select one option");

    return View();
}

with the below code i can validate any checkboxes is selected or not from server side code and add model error which show error at client side.

but i want to do validation by client side using normal data annotation.

see my razor code

<div class="row">
    <div class="col-md-8">
        <section id="testform">
            @using (Html.BeginForm("Index", "Customers", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
            {
                @Html.AntiForgeryToken()
                <h4>Enter customer info.</h4>
                <hr />
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                <div class="form-group">
                    @Html.LabelFor(m => m.FirstName, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.FirstName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="form-group">
                    @Html.LabelFor(m => m.LastName, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.LastName, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.LastName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <div class="checkbox">
                            @Html.CheckBoxFor(m => m.SelfSend)
                            @Html.LabelFor(m => m.SelfSend)
                        </div>
                    </div>

                    <div class="col-md-offset-2 col-md-10">
                        <div class="checkbox">
                            @Html.CheckBoxFor(m => m.thirdParty)
                            @Html.LabelFor(m => m.thirdParty)
                        </div>
                    </div>

                    <div class="col-md-offset-2 col-md-10">
                        <div class="checkbox">
                            @Html.CheckBoxFor(m => m.Others)
                            @Html.LabelFor(m => m.Others)
                        </div>
                    </div>
                    <div class="col-md-offset-2 col-md-10">
                        @Html.ValidationMessage("Error", "", new { @class = "text-danger" })
                    </div>
                    </div>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" value="Save" class="btn btn-default" />
                    </div>
                </div>

            }
        </section>
    </div>
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
9
  • What problem are you facing? Is there an error? Commented Jul 21, 2018 at 20:06
  • i have to use checkbox as per spec but one checkbox must be selected before form submitted. how to do client side validation by annotation? Commented Jul 21, 2018 at 20:07
  • You can use the RangeAttribute but you will need some custom JavaScript to populate a hidden item. Commented Jul 21, 2018 at 20:21
  • share some hint where i can use range attribute for bool property. share some url. thanks Commented Jul 21, 2018 at 20:31
  • There's a link in the comment. You are not validating the checkbox directly but computing the number of checkboxes selected. Commented Jul 21, 2018 at 20:35

2 Answers 2

2

You can try to write a customer model validation attribute.

add CheckBoxAuthAttribute in your one of three validation property.

There is a method protected virtual ValidationResult IsValid(object value, ValidationContext validationContext) in you can override inValidationAttribute.

public class CheckBoxAuthAttribute : ValidationAttribute
{
    public CheckBoxAuthAttribute(params string[] propertyNames)
    {
        this.PropertyNames = propertyNames;
    }

    public string[] PropertyNames { get; private set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var properties = this.PropertyNames.Select(validationContext.ObjectType.GetProperty);
        var values = properties
                .Select(p => p.GetValue(validationContext.ObjectInstance, null))
                .OfType<bool>();

        if (values.Contains(true) || (bool)value == true)
        {
            return null;
        }
        return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
    }
}
public class Customer
{
    [Required]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }

    [Display(Name = "Mail to me")]
    [CheckBoxAuth("thirdParty", "Others", ErrorMessage = "Must select one option"))]
    public bool SelfSend { get; set; }

    [Display(Name = "3rd party")]
    public bool thirdParty { get; set; }

    [Display(Name = "Others")]
    public bool Others { get; set; }
}
Sign up to request clarification or add additional context in comments.

2 Comments

this validation fire at server side but i am looking for a attribute which will fire client side first too.
You can use jquery validation library with asp.net MVC validation Attribute here is a link wish can help you c-sharpcorner.com/article/asp-net-mvc5-jquery-form-validator
2

Since you want one of 3 possible options to be selected, then use radio buttons and bind to a property with a required attribute.

Start by defining a view model

public class CustomerVM
{
    [Required]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }
    [Required]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }
    [Required]
    public int? Mailing { get; set; } // see notes below
}

And in the view

@model CustomerVM
....
@using (Html.BeginForm())
{
    ....
    <label>
        @Html.RadioButtonFor(m => m.Mailing, 1, new { id = ""})
        <span>Mail to me</span>
    </label>
    <label>
        @Html.RadioButtonFor(m => m.Mailing, 2, new { id = ""})
        <span>3rd party</span>
    </label>
    .... // ditto for "Others"
    @Html.ValidationMessageFor(m => m.Mailing)
    ....
}

and the POST method will be

[HttpPost]
public ActionResult Index(CustomerVM model)
{
    if(!ModelState.IsValid)
    {
        return View(model);
    }
    .... // map to instance of data model, save and redirect
}

Note that if these options are unlikely to change, it would be more appropriate to make the property an enum rather than an int, for example

public enum Mailing
{
    [Display(Name = "Mail to me")]
    SelfSend = 1,
    [Display(Name = "3rd party")]
    ThirdParty = 2,
    [Display(Name = "Others")]
    Others = 3
}

public class CustomerVM
{
    ....
    [Required]
    public Mailing? Mailing { get; set; }
}

and the view code would be

@Html.RadioButtonFor(m => m.Mailing, Mailing.SelfSend, new { id = ""})

2 Comments

Thank you sir. radio buttons are mutually exclusive but in my case i have to use checkbox because user may select 3 option or user one option. so guide me how to handle this situation if user select no option then i have to show a error message at client side by not normal data annotation.
Then use the mvc-collectionvalidation project I noted in the comments to your question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.