I am using the Data Annotation Validator, outlined here:
http://www.asp.net/learn/mvc/tutorial-39-cs.aspx
The Data Annotations Model Binder is on codeplex:
http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471
I've downloaded the code, built it, and referenced the new System.ComponentModel.DataAnnotations.dll. I've also set the default model binder to use Microsoft.Web.Mvc.DataAnnotations.dll. It works fine when binding to a simple object (e.g, Order), but if I bind to an Order that has a CreditCard object, I get an error in the new binder:
Object reference not set to an instance of an object, DataAnnotationsModelBinder.cs Line: 60.
In my example, the fullPropertyKey is "Card", and modelState is null, so its obviously having an issue with the Card property of Order.
ModelState modelState = bindingContext.ModelState[fullPropertyKey];
// Only validate and bind if the property itself has no errors
if (modelState.Errors.Count == 0) {
if (OnPropertyValidating(controllerContext, bindingContext, propertyDescriptor, newPropertyValue)) {
SetProperty(controllerContext, bindingContext, propertyDescriptor, newPropertyValue);
OnPropertyValidated(controllerContext, bindingContext, propertyDescriptor, newPropertyValue);
}
}
Does the data annotaions binder support this? The stock binder has no issue with the Order -> CreditCard structure (minus the validation, of course). Test code:
Controller & Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.ComponentModel.DataAnnotations;
namespace PAW.Controllers
{
//MODEL
public class Order
{
[Required]
[DataType(DataType.Text)]
[StringLength(5)]
public string CustomerName { get; set; }
public CreditCard Card { get; set; }
public Order()
{
this.Card = new CreditCard();
}
}
public class CreditCard
{
[StringLength(16), Required]
public string Number { get; set; }
}
//CONTROLLER
public class TestController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index()
{
return View(new Order());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(Order o)
{
if (ModelState.IsValid)
{
//update
}
return View(o);
}
}
}
The View:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<PAW.Controllers.Order>" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
<% using(Html.BeginForm()) { %>
<%=Html.ValidationSummary("Errors: ") %>
<div>
Name (max 5 chars): <%=Html.TextBox("CustomerName", Model.CustomerName)%>
</div>
<div>
CC#: <%=Html.TextBox("Card.Number", Model.Card.Number)%>
</div>
<input type="submit" value="submit" />
<% } %>
</body>
</html>