Brosteins

Developers, Technology Evangelists, Bros.

MVC Validation Extensions

What are MVC Validation Extensions?

MVC Validation Extensions is a library that builds upon ASP.NET MVC by providing additional validation attributes to use.

 

 

Features

  • Familiar usage by extending ASP.NET MVC data annotations
  • Client and server validation methods
  • Dynamic comparison of dates or numeric fields
  • Model attributes

Getting Started
To get started with the additional attributes just install the MVCValidationExtensions nuget package into your solution.  Add the appropriate attributes to your models.

Additional Implemented Attributes

  • Comparison – Validates that the property meets the comparison with the specified other property
    • GreaterThan
    • GreaterThanEqualTo
    • LessThan
    • LessThanEqualTo
  • RequiredIf – Causes the property to be required if the specified other property is not null
  • RequiredIfValue – Causes the property to be required if the specified other property is equal to the specified other value
  • RequiredIfAnyValue – Causes the property to be required if the specified other property is equal to any of the specified other values
  • RequiredIfEmpty – Causes the property to be required if the specified other property is empty (whitespace is considered empty)

Usage
Using the MVC Validation Extensions is simple because they are used the same way the current validation attributes are.

Given the following Model…

public class TestModel
    {
        [RequiredIf("RequiredIntControl")]
        public int? SomeIntThatMightBeRequired { get; set; }

        [RequiredIfValue("RequiredIntControl", "15")]
        public int? SomeRequiredIfValue { get; set; }

        public string RequiredIntControl { get; set; }

        [RequiredIfAnyValue("RequiredIfAnyValueControl", new []{"ValOne", "ValTwo", "ValThree"})] 
        public int? RequiredIfAnyValue { get; set; } 
        public string RequiredIfAnyValueControl { get; set; }
        [DisplayName("> Hidden Int")]
        [GreaterThan("HiddentInt")]
        public int? SomeValue { get; set; }

        [Required]
        [GreaterThan("SomeValue", ErrorMessage = "Overriding the error message.")]
        public int? RequiredInt { get; set; }

        [Required]
        [DisplayName("< Date")]
        [LessThan("SomeOtherDate")]
        public DateTime? SomeDate { get; set; }

        [DisplayName("<= Some Other Date")]
        [LessThanEqualTo("HiddenDateTime")]
        public DateTime? SomeOtherDate { get; set; }

        [DisplayName(">= Kendo Date")]
        [GreaterThanEqualTo("KendoDateOther")]
        public DateTime? KendoDate { get; set; }

        public int? HiddentInt { get; set; }
        public DateTime? HiddenDateTime { get; set; }
        public DateTime? KendoDateOther { get; set; }
    }

We get the following results…

 

mvc validation extensions example

 

mvc validation extensions 1.1.2

Required and valid.

Share

29 comments for “MVC Validation Extensions

  1. kam
    February 22, 2016 at 12:25 pm

    how to do group validation?

    • Nick Branstein
      March 2, 2016 at 10:30 am

      Kam,

      Can you be more specific as to the scenario that you are having trouble validating?

  2. Stephen Welch
    April 6, 2016 at 2:28 pm

    I am using your MVC validation extensions within a modal that is loaded via ajax and showing/hiding controls based on selections. Since the form is reloading, in order for the unobtrusive validation to occur I had to manually call the unobtrusive jquery validation:

    $(document).on(‘click’, ‘#btnSave’, function () {
    $.validator.unobtrusive.parse(“#preceptorform”);
    });

    but this doesnt seem to work with your mvcvalidationextensions.unobtrusive.js functionality since the validator works on first load, then stops working the second time. Is there a way that I can call your checks within the button click of the modal?

    • Nick Branstein
      April 8, 2016 at 9:39 am

      Stephen,

      This is what I typically do after loading in a new form via Ajax:

      var form = $(‘form’);
      form.removeData(‘validator’);
      form.removeData(‘unobtrusiveValidation’);
      $.validator.unobtrusive.parse(form);

      This will parse the entire form which I have not had any issues with. If you still have issues are you able to setup a jsfiddle or jsbin and I can help you take a closer look?

  3. Stephen Welch
    April 8, 2016 at 7:18 pm

    thank you! This worked!

  4. Alan Kaeser
    May 18, 2016 at 3:31 pm

    Does this work with Html.EditorFor in Razor Forms:
    Here is my Model:
    [DisplayName(“Start Date”)]
    [Required(ErrorMessage=”A Start Date is Required”)]
    public DateTime? StartDate
    {
    get; set;
    }

    [DisplayName(“End Date”)]
    [Required(ErrorMessage = “An End Date is Required”)]
    [GreaterThanEqualTo(“StartDate”, ErrorMessage =”End Date Must be later than the StartDate”)]
    public DateTime? EndDate
    {
    get; set;
    }

    Here is my CSHTML:

    @Html.ValidationSummary(true, “”, new
    {
    @class = “text-danger”
    })

    @Html.LabelFor(m => m.StartDate, new
    {
    @class = “col-md-3 control-label”
    })

    @Html.EditorFor(m => m.StartDate)

    @Html.ValidationMessageFor(m => m.StartDate, “”, new
    {
    @class = “text-danger”
    })

    @Html.LabelFor(m => m.EndDate, new
    {
    @class = “col-md-3 control-label”
    })

    @Html.EditorFor(m => m.EndDate)

    @Html.ValidationMessageFor(m => m.EndDate, “”, new
    {
    @class = “text-danger”
    })

    I don’t get any validation message if I put a start date > the end date.
    I have jquery.validate.unobstrusive loaded with my bundles. I get an error if I don’t enter anything in the date fields.

    • Alan Kaeser
      May 20, 2016 at 4:37 pm

      I figured out the issue. I didn’t have the script loaded in my bundle. Not sure if I ever saw that in the installation instructions.

  5. Janet
    June 30, 2016 at 4:42 pm

    What is the best method to use for determine if the checkbox is true. We are try RequiredIFValue(); but I doesn’t seem to work

    • Nick Branstein
      July 17, 2016 at 9:30 am

      You can use the RequiredIf attribute for checkboxes. If you are setting different values on checkboxes other than default True/False you’d want to use RequiredIfValue.

  6. Rahul Savaliya
    December 8, 2016 at 1:42 am

    I have used RequiredIFValue in bool? property. and seems like it is not working. can you suggest way how to apply RequiredIFValue in bool? property.

    • Nick Branstein
      December 13, 2016 at 9:31 am

      Is there any way you can post your model and view code to Github perhaps?

  7. Tirthak
    December 8, 2016 at 7:03 am

    How can we use same attribute multiple times on same property?
    For example :-

    RequiredIf(someproperty1,1)
    RequiredIf(someproperty2,2)
    RequiredIf(someproperty3,3)
    public string property {get; set;}

    • Nick Branstein
      December 13, 2016 at 9:33 am

      Unfortunately it will not work like this. This would require a new extension.

  8. Ivy B
    December 29, 2016 at 10:08 am

    How can you skip form validation for those html elements that are hidden? I have two elements, Min and Max that get validated even if they are hidden which makes my form put out an error.

    • Nick Branstein
      January 3, 2017 at 10:15 am

      This is actually probably a better question for jQuery validate, however, the default settings of jQuery validate are set to ignore hidden fields so anything hidden should not be causing validation.

      They best I can do without seeing your full model and view code is that you can override or reconfigure jQuery validate with something like the following:

      var inputForm = $(‘form’);

      if ($.data(inputForm[0], ‘validator’)) {
      $.data(inputForm[0], ‘validator’).settings.ignore = ‘:hidden’;
      }

      Where ‘:hidden’ is a selector as to the elements that you want ignored.

  9. Stephen Welch
    March 23, 2017 at 10:07 am

    Hi Nick!

    I have a viewmodel like this:

    Public Class nomination
    {
    [DataType(DataType.Upload)]
    [Required(ErrorMessage =”You must upload a letter.”)]
    [FileType(“doc,docx,pdf,DOC,DOCX,PDF”, ErrorMessage =”Must upload DOC, DOCX, or PDF file.”)]

    public HttpPostedFileBase FileUpload { get; set; }

    [Required]
    public List committees { get; set; } = Helpers.helpers.getCommittees();
    }

    public class committeeVM
    {
    public int commid { get; set; }
    public string commname { get; set; }

    public bool isselected { get; set; }
    }

    TheCommitteeVM is the results of a checkbox list (isselected is true if one is selected…)

    I am needing to require the file upload IF one of the nominations.Committees.isselected = true and the nominations.Committees.commid is a specific value, say 2 or 3.

    Is there a way to use the extensions to accomplish this when the property is part of a list object within the viewmodel?

    • Nick Branstein
      April 3, 2017 at 12:42 pm

      Unfortunately the validation extensions won’t be able to pull from a collection so this is something that you will need to check manually.

  10. Chris
    May 4, 2017 at 5:26 pm

    Nick, I downloaded your extension into my project and I’m trying to trigger the validation in a Modal window. Regular data annotations will display ok, but the ones from your extension break the modal and refresh the page and display without styles.

    MODEL LOOKS LIKE THIS:

    public int ContactID { get; set; }
    [Required]
    [DisplayName(“Category”)]
    public int CategoryID { get; set; }
    [Required]
    [DisplayName(“Level”)]
    public int LevelTypeID { get; set; }

    [RequiredIfValue(“CategoryID”, “1”)]
    [DisplayName(“First Name”)]
    public string FirstName { get; set; }

    [RequiredIfValue(“CategoryID”, “1”)]
    [DisplayName(“Last Name”)]
    public string LastName { get; set; }

    [RequiredIfValue(“CategoryID”, “2”)]
    public string Company { get; set; }

    ____________________________________________

    PARTIAL VIEW LOOKS LIKE THIS:

    @model AutomationPro.Contact

    @*http://~/Scripts/jquery.validate.unobtrusive.min.js*@

    $(“#firstname1”).hide();
    $(“#firstname2”).hide();
    $(“#firstname3”).hide();
    $(“#lastname1”).hide();
    $(“#lastname2”).hide();
    $(“#lastname3”).hide();
    $(“#company1”).hide();
    $(“#company2”).hide();
    $(“#company3”).hide();

    $(document).ready(function () {
    $(‘#category’).on(‘change’, function () {
    if (this.value == ‘1’)

    {
    $(“#firstname1”).show();
    $(“#firstname2”).show();
    $(“#firstname3”).show();
    $(“#lastname1”).show();
    $(“#lastname2”).show();
    $(“#lastname3”).show();
    $(“#company1”).hide();
    $(“#company2”).hide();
    $(“#company3”).hide();

    }
    else {
    $(“#firstname1”).hide();
    $(“#firstname2”).hide();
    $(“#firstname3”).hide();
    $(“#lastname1”).hide();
    $(“#lastname2”).hide();
    $(“#lastname3”).hide();
    $(“#company1”).show();
    $(“#company2”).show();
    $(“#company3”).show();

    }

    });
    });

    ×
      Contact

    @using (Html.BeginForm(null, null, FormMethod.Post, new { @enctype = “multipart/form-data”, id = “createContactchoice” }))
    {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true, “”, new { @class = “text-danger” })
    @Html.HiddenFor(model => model.ContactID)
    @Html.HiddenFor(model => model.LevelTypeID)

    Category

    @Html.DropDownList(“CategoryID”, ViewBag.Categories as SelectList, String.Empty, new { @class = “form-control”, id = “category” })
    @Html.ValidationMessageFor(model => model.CategoryID, “”, new { @class = “text-danger” })


    @Html.EditorFor(model => model.ContactTypes)

    First Name

    @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = “form-control” } })
    @Html.ValidationMessageFor(model => model.FirstName, “”, new { @class = “text-danger” })

    Last Name

    @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = “form-control” } })
    @Html.ValidationMessageFor(model => model.LastName, “”, new { @class = “text-danger” })

    Company

    @Html.EditorFor(model => model.Company, new { htmlAttributes = new { @class = “form-control” } })
    @Html.ValidationMessageFor(model => model.Company, “”, new { @class = “text-danger” })

     
    Cancel


    }

    • Nick Branstein
      May 12, 2017 at 5:00 pm

      I’m assuming the partial view is the one that is loaded into the modal. There shouldn’t be any issues with the extensions in a modal or a popup. Can you open your dev tools and check to see if you have any javascript errors in the console when the modal opens up or when the validation should be firing?

  11. Cam
    May 11, 2018 at 5:09 pm

    I just added version 1.1.4.0 to my site. Server side validation is working but the client side validation isn’t. are there any additional steps I need to take to get the client side to work as expected?

    • Cam
      May 11, 2018 at 5:12 pm

      Sorry you can ignore this…. totally didn’t see the “/mvcvalidationextensions.unobtrusive.js” in my project. Sorry.

  12. Stephen Welch
    September 15, 2018 at 9:15 pm

    Any plans to make these great validators for .net Core?

    • Nick Branstein
      September 16, 2018 at 9:49 am

      Yes I would like to do this eventually but I don’t really have a timetable at the moment.

  13. Cam
    September 18, 2018 at 1:20 pm

    Do you need to do something different to get the validation to work when the field is part of a collection? I had it working and then the client asked to be able to add multiples of a particular item, so I am dynamically adding a chunk of HTML VIA ajax, I am doing the whole:

    var form = $(‘form’);
    form.removeData(‘validator’);
    form.removeData(‘unobtrusiveValidation’);
    $.validator.unobtrusive.parse(form);

    thing after my HTML has been loaded. And all of the other validations are working (my regex format validation and such), but not the RequiredIf. I am just wondering if it is going to be able to find the property now that it has been prefixed…..

    [RequiredIf(“MyProperty”)]
    … the field that needs to be required if MyProperty is set …

    I am rendering out the multiples inside a
    Html.BeginCollectionItem(“MyProperties”)

    block so they are rendering out with IDs like:
    MyProperties_fd6f09cc-1646-42f4-84e0-7c4a79df9ab0__MyProperty

    The field’s HTML looks like:
    data-val-requiredif-otherproperty=”MyProperty”
    but I am linking it should be:
    data-val-requiredif-otherproperty=”MyProperties_fd6f09cc-1646-42f4-84e0-7c4a79df9ab0__MyProperty”

    Am I missing something?

    Thanks

    • Cameron Charlebois
      September 18, 2018 at 1:28 pm

      If I mess around with the HTML in chrome dev tools. If I set the attribute to:
      data-val-requiredif-otherproperty=”MyProperties[fd6f09cc-1646-42f4-84e0-7c4a79df9ab0]MyProperty”

      And do the reparse form validation stuff then it works. Looks like the field prefix isn’t being respected as part of the attribute creation.

      • Nick Branstein
        September 24, 2018 at 8:19 pm

        You’re correct. Ya unfortunately it isn’t designed to work with a collection like that. The javascript would need to know the exact name that it needs to depend on. I haven’t really looked into this before so I’m not quite sure it is possible or not (I imagine it is) but just not supported right now.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.