Best Practices ViewModel Validation in ASP.NET MVC

To answer your 3th question first: No there is no easier way then what you are doing. Two lines of code to get it working can hardly be easier. Although there is a plug-in you could use, like explained in the question unobtrusive validation not working with dynamic content

Your first question, how to centralize validation, I normally use a separate class file to store all my validation rules. This way I don’t have to browse through every single class file to find the rules, but have them all in one place. If that’s better, is matter of choice. The main reason I started to use it, is to be able to add validation to auto-generated classes, like classes from the Entity Framework.

So I have a file called ModelValidation.cs in my data layer, and have code for all my models like

/// <summary>
/// Validation rules for the <see cref="Test"/> object
/// </summary>
/// <remarks>
/// 2015-01-26: Created
/// </remarks>
[MetadataType(typeof(TestValidation))]
public partial class Test { }
public class TestValidation
{
    /// <summary>Name is required</summary>
    [Required]
    [StringLength(100)]
    public string Name { get; set; }

    /// <summary>Text is multiline</summary>
    [DataType(DataType.MultilineText)]
    [AllowHtml]
    public string Text { get; set; }
}

Now as you noticed I don’t provide the actual error message. I use conventions by Haacked to add the messages. It makes it simple to add localized validation rules.

It basically comes down to a recource file containing something like:

Test_Name = "Provide name"
Test_Name_Required = "Name is required"

And these messages and naming will be used when you call regular MVC view code like

<div class="editor-container">
    <div class="editor-label">
        @Html.LabelFor(model => model.Name) <!--"Provide name"-->
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Name)
        @Html.ValidationMessageFor(model => model.Name) <!--"Name is required"-->
    </div>
</div>

Your second question, about different validation for add/edit can be handled in two ways. The best way, would be to use views as they are actually intended. That means you don’t pass your actual models to the views, but you create a view model that contains only the data. So you have a view model for Create with the proper validation rules and a view model for Edit with the proper rules, and when they pass you insert the result in your actual model.
This however requires a lot more code and manual work, so I can imagine you’re not really willing to do it like this.

Another option would be to use conditional validation like explained by viperguynaz. Now instead of a boolean, my classes that require a change between edit/add have a primary key Id int. So I check if Id>0 to determine if it is an edit or not.

UPDATE:

If you want to update validation on every ajax call, you could use jQuery ajaxComplete. This will revalidate all forms after every ajax request.

$( document ).ajaxComplete(function() {
    $('form').each(function() {
        var $el = $(this);
        $el.data('validator', null); 
        $.validator.unobtrusive.parse($el);
    })
});

If this is something you want, depends on how often you receive a form via AJAX. If you have a lot of AJAX request, like polling a status every 10seconds, than you don’t want this. If you have an occasional AJAX request, that mostly contains a form, then you could use it.

If your AJAX returns a form you want to validate, then yes, it is good practise to update the validation. But I guess a better question would be “Do I really need to send the form by AJAX?”
AJAX is fun and useful, but it should be used with care and thought.

Leave a Comment