MVC3 Client/Server Validation

Published 1/30/2012 by James in ASP.NET MVC

I started working at Dominion Digital a little over a week ago and I have already learned so much. I have tinkered with MVC3 on a very small scale, but nothing compared to what I am doing now. In just the first week I have gaining a solid understanding of the importance of a ViewModel and just how easy it is to add both Client and Server-side validation code to your models. Prior to coming here, I would validate on the client using my own jQuery code, and then validate on the server using attributes in System.ComponentModel.DataAnnotations. Validation has been simplified, see my Model below:

using System.ComponentModel.DataAnnotations;

namespace ViewModelExample.Models
{
  public class Person
  {
    [Required(AllowEmptyStrings=false, ErrorMessage="Please enter your First Name!")]
    public string FirstName { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Please enter your Last Name!")]    
    public string LastName { get; set; }

    [Range(18, 100, ErrorMessage="Your age must be between 18 and 60.")]
    public int Age { get; set; }
  }
}

Here we are setting three properties FirstName (required), LastName (required), and Age (range between 18 and 100). The ViewModel, which probably not needed at this time but the View could change over time:

using ViewModelExample.Models;

namespace ViewModelExample.ViewModels
{
  public class PersonVM
  {
    public Person Person { get; set; }
  }
}

My Action:

[HttpPost]
public ActionResult Save(PersonVM personVM)
{
    if (ModelState.IsValid)
    {
        var person = new Person()
        {
            FirstName = personVM.Person.FirstName,
            LastName = personVM.Person.LastName,
            Age = personVM.Person.Age
        };

        return View(new PersonVM()
        {
            Person = person
        });
    }

    return View("New");
}

...and the Index View:

@using ViewModelExample.ViewModels
@model PersonVM
       
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@using( Html.BeginForm("Save","Person", FormMethod.Post ) )
{
    @Html.ValidationSummary(false)

    @Html.LabelFor(p => p.Person.FirstName, "First Name")
    @Html.TextBoxFor(p => p.Person.FirstName)
    @Html.ValidationMessageFor(p => p.Person.FirstName)
    <br />
    @Html.LabelFor(p => p.Person.LastName, "Last Name")
    @Html.TextBoxFor(p => p.Person.LastName)
    @Html.ValidationMessageFor(p => p.Person.LastName)
    <br />
    @Html.LabelFor(p => p.Person.Age, "Age")
    @Html.TextBoxFor(p => p.Person.Age)
    @Html.ValidationMessageFor(p => p.Person.Age)
    <br />
    <input type="submit" value="Save" />
}

Now if you set a break point on the Action method, you clearly see this is posting to the web server on every button click. Now look at how simple it is to add client-side validation. First, go to the NuGet package manager and run the following commands:

Install-Package DataAnnotationsExtensions
Install-Package DataAnnotationsExtensions.MVC3

Now throw the following lines in your _Layout.cshtml file:

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

Without anymore work, you have added client-side validation and the best part of it is that all of the rules are written right in the Models themselves.


setInterval()

Published 1/14/2012 by James in ASP.NET MVC | jQuery

I read an interesting article today around periodically updating data in an MVC view on set intervals. It was rather simple and uses a setInterval() javascript method.

First we setup a method, GetDateTime(), that returns a PartialViewResult that I will call via a GET request. I then setup the initial controller action, Index(), and reuse the GetDateTime() method to bind the DateTime to the ViewBag.

public ActionResult Index()
{
    ViewBag.DateTime =  GetDateTime().ViewBag.DateTime;
    return View();
}

public PartialViewResult GetDateTime()
{
    ViewBag.DateTime = DateTime.Now;
    return PartialView( "Time" );
}

My PartialView, named Time, looks a little like this:

<span id="time">@ViewBag.DateTime</span>

And the Index View looks like this:

<div id="content">@{ Html.RenderPartial( "Time", ( object ) ViewBag.DateTime ); }</div>

Now if you run this as is, the page should render the current time, without a refresh. Now let's wire the Index view with a little javascript to refresh in intervals.

<script type="text/javascript">
    $(function () {
        setInterval(function () {
            $('#content').load('Home/GetDateTime');
        }, 1000);
    });
</script>

This setInterval function basically takes two parameters, in this example. The first is the code to execute, and the second parameter is the interval, in milliseconds. Here, our first parameter uses the jquery load method to make a GET request to the specified URL, every second. The result returned is assigned to the DOM element that matches the jQuery selector, the <div> with the id of 'content'. For more on the setInterval method, click here.

This is an extremely simplistic example, and considerations should be thought out prior to implementing this type of polling. I would imagine in a heavy traffic environment that given the interval and the data returned, this could get expensive.


$.ajax() statusCode setting

Published 9/7/2011 by James

I learned something really interesting today. The jQuery ajax function has a statusCode setting that allows you to respond to HTTP status codes differently.

$.ajax({
    url: 'Default.aspx/GetDater',
    type: 'POST',
    contentType: 'application/json',
    dataType: 'json',
    error: function(jqXHR, textStatus, errorThrown) { alert('error'); },
    statusCode: {
        200: function() { alert('a 200 occurred'); },
        500: function() { alert('a 500 occurred'); },
        409: function(jqXHR, textStatus, errorThrown) {
            if (errorThrown == 'Conflict') {
                alert('user exists');
            }
        }
    }
});

In this function I am wiring handlers to respond to status codes, 200, 500, and 409. Something else worth mentioning here is if you declare a success and/or error method in this ajax call, it will fire prior to the statusCode handler. You can learn more about this setting and other ajax settings here.

James


.NET Fanatic

fa·nat·ic /fəˈnatik/
Noun: A person marked or motivated by an extreme, unreasoning enthusiasm, as for a cause or software development...specifically .NET.