About Us

Serializing ModelState errors in a json call

by Travis Ellis 4. February 2013 01:31

In ASP.net MVC, the ModelStateDictionary class contains all of the validation errors for your models that get posted from your forms. The HTML helpers Html.ValidationSummary and Html.ValidationMessageFor will look at the Model State to display these validation messages. When you are submitting your form with an AJAX request and return a JSON response, then you need to have a way to return these validation errors to your views. Here is a helpful extension method that will allow you to do that:

public static class ModelStateExtensions
{
    public static IDictionary ToSerializedDictionary(this ModelStateDictionary modelState)
    {
        return modelState.ToDictionary(
            k => k.Key,
            v => v.Value.Errors.Select(x => x.ErrorMessage).ToArray()
        );
    }
}

Now in your controller action you can return this data back to your view:

[HttpPost]
public ActionResult Create(ProjectModel model)
{
    // Validation Errors
    if(!ModelState.IsValid)
    {
        return Json(ModelState.ToSerializedDictionary());
    }

    // Success - Save Project data
}
}

In your view you can now write some javascript code to display the errors in your view.

Injecting a dependency into an action filter using ninject

by Travis Ellis 20. November 2012 04:06

One of the most powerful features of using Inversion of Control/Dependency Injection is the ability to have highly testable code. When your dependencies are interfaces instead of concrete classes, it makes it very easy for a unit test to mock that dependency:

public class ProductsController : Controller
{
    protected readonly IProductService productService;
 
    public ProductsController(IProductService productService)
    {
        this.productService = productService;
    }

    [HttpPost]
    public ActionResult GetProducts()
    {
        return Json(productService.GetAllProducts());
    }
}

The above example shows an MVC controller that takes a single dependency: IProductService. There is a single action method that is using the service to get a list of products, which is being returned via JSON. Since the dependency is defined as an interface, the code is very easy to test with a mocking framework.

What happens when you want to apply the same concept to an Action Filter? Action Filters are attributes that are added to your controllers and actions at compile time so you can’t pass a dependency through the constructor. Well, with Ninject you can.

Using NuGet, install the Ninject.MVC3 package (also works in MVC 4). This will add both the Ninject and Ninject MVC packages and add a file  called NinjectWebCommon.cs to the App_Start folder in your solution. This is where we will set up the dependency injection for our action filters. Before we can do that we will need to create our action filter.

For this example we will create a simple filter that could be used for logging. The first thing you need to do is create a dummy attribute that you can apply to your action methods:

public enum SeverityLevel
{
    Warning,
    Information
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class LogAttribute : FilterAttribute
{
    public LogLevel Level { get; set; }

    public LogAttribute(LogLevel level)
    {
        this.Level = level;
    }
}

This can be applied to your action methods as follows:

[Log(SeverityLevel.Information)]
public Actionresult Index()
{
    return View();
}

This attribute by itself does nothing, but it will be used as a hook to inject a dependency into our real filter:

public class LogFilter : IActionFilter
{
    protected readonly ILogService logService;
    protected readonly LogLevel level;

    public LogFilter(ILogService logService, LogLevel level)
    {
        this.logService = logService;
        this.level = level;
    }

    public void OnActionExecuted(ActionExecutedContext filterContext
    {
        // implement logging logic here
        this.logService.Log(...);
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // implement logging logic here
        this.logService.Log(...);
    }
}

You can now write unit tests against the filter class and mock up your dependency using a mocking framework, but there is one more thing we need to do to wire everything that is up. Right now our filter has no direct tie to our attribute. Let’s change that by adding the following code to the NinjectWebCommon class in the RegisterServices method:

private static void RegisterServices(IKernel kernel)
{
    kernel.BindFilter<LogFilter>(FilterScope.Action, 0)
        .WhenActionMethodHas<LogAttribute>()
        .WithConstructorArgumentFromActionAttribute<LogAttribute>("level", attr => attr.Level);
}

The BindFilter is is an extension method that exists in the Ninject.Web.Mvc.FilterBindingSyntax namespace. Once you add this line whenever Ninject creates an action method that has the LogAttribute applied to it, it will automatically apply the LogFilter and inject any dependencies that it knows how to create. That is all you need to get dependency injection working on an MVC action filter.

A Quick Introduction to Fluent Validation in ASP.net MVC

by Travis Ellis 2. April 2012 20:03

In one of the projects I am working on we are using ASP.net MVC for our web front-end. I love the framework but I have never really been thrilled about validation using the DataAnnotations library. Based on the recommendation of some other people I discovered the FluentValidation library. The goal of this post is to show you how to create a very simple MVC application using FluentValidation as an alternative to DataAnnotations.

The first thing you need to do is create a new MVC Application using Visual Studio 2010:

image

The template you choose does not matter but for this post I am using the Internet Application template. There won’t be any authentication in the application so the Intranet template will work fine too.

Once the project is created right-click on the References item in Solution Explorer and click Manage NuGet Packages (if you do not see this menu then make sure you download the most recent version of NuGet from NuGet.org):

image

This will bring up the Package Manager dialog. In the Search box, type in FluentValidation and hit Enter. You should see a few packages in the results list. The one you want to add to the project is FluentValidation.MVC3. This will install the FluentValidation MVC3 package and FluentValidation itself (the MVC3 package depends on it). Select the FluentValidation.MVC3 package in the list and click the Install button:

image

Once the assemblies are added to the Solution, you can close the Package Manager and open the Global.asax file in the root directory of your project. You need to add a single line to your project to configure the framework to work with MVC. In the Application_Start method in Global.asax, add the following line:

FluentValidation.Mvc.FluentValidationModelValidatorProvider.Configure();

Once you have done this we can create a new Model class that will be used by one of our Views/Controllers:


public class RegistrationModel
{
    public string Username { get; set; }
    public string Password { get; set; }
    public string ConfirmPassword { get; set; }
    public DateTime BirthDate { get; set; }
    public int NumberOfChildren { get; set; }     
}

This is a simple model used to register for a website. It asks for a username, password (with confirmation), date of birth and number of children. Now that we have a model we can create the controller actions for it. We will need a GET and POST action:


[HttpGet]
public ActionResult Create()
{
    return View();
}

[HttpPost]
public ActionResult Create(RegistrationModel model)
{
    if(!ModelState.IsValid)
    {
        return View(model);
    }
    
    // register here

    return RedirectToAction("Index", "Home");
}

The code here is pretty bare and more than likely identical to the code that would be used when using DataAnnotations to do the validation. If you were to run the code right now there would be no validation. Let's fix that by creating a new validator class:


public class RegistrationValidator : AbstractValidator
{
    public RegistrationValidator()
    {
        RuleFor(model => model.Username)
            .NotEmpty()
            .Length(1, 256);

        RuleFor(model => model.Password)
            .NotEmpty()
            .Length(1, 50);

        RuleFor(model => model.ConfirmPassword)
            .NotEmpty()
            .Equal(model => model.Password);

        RuleFor(model => model.DateofBirth)
            .GreaterThanOrEqual(DateTime.Today.AddYears(-18));

        RuleFor(model => model.NumberOfChildren)
            .NotNull()
            .GreaterThan(0)
            .NotEqual(13);
    }
}

We have defined the following rules for our model:

  • Username is required and must be between 1 and 256 characters long.
  • Password is required and must be between 1 and 50 characters long.
  • Password confirmation is required and must match the password.
  • The Date of Birth must be greater than or equal to todays date 18 years ago (to confirm they are 18 or older).
  • User must have at least one child but can not have 13 (we are very superstitious).

Now that we have our validations in place, we need to update our model to include an attribute that will wire up the validation with MVC. Add the following attribute to our RegistrationModel class:


[Validator(typeof(RegistrationModel))]
public class RegistrationModel

That is all that is needed to use FluentValidation. The same rules apply when using client side validation. You need to include jQuery, jQuery Validation and optionally include jQuery Unobtrusive Validation scripts. These steps are no different than using DataAnnotations so it's very simple to convert a site to use the framework. If you are using Dependency Injection then you can also create your own validator factory that will wire up the validators for you so you don't need to register the type of validator on each model you create. If you use Ninject, there is already a NuGet package that has a validator factory that you can use. Just open up the NuGet package manager and search for Ninject.Extensions.FluentValidation.

FluentValidation is a very powerful framework. There are plenty of built in validators that you can use such as verifying a credit card or e-mail address. Creating your own custom validators is also very simple. Head on over to the CodePlex page today and look at the documentation to start using it in your projects.