# 10 Kasım 2008 Pazartesi
I'm sure someone did this before, but I'm too lazy to search for it :)

Model Binders in MVC is a cool concept to map your form values to parameter objects of your Action. There's also this automatic error message display capabilities in MVC. All explained by The Gu here.

Here's my take on validating a model object during the binding process. Castle project has a validation framework and a range of validators which can be used standalone. It would be cool to use it with MVC to ease the validation pain a bit, huh?

First, we need a binder to validate the object using Castle's ValidatorRunner:

    using System.Web.Mvc;
    using Castle.Components.Validator;
 
    public class ValidatingModelBinder : DefaultModelBinder
    {
        public override ModelBinderResult BindModel(ModelBindingContext bindingContext)
        {
            var result = base.BindModel(bindingContext);
 
            if (result != null && result.Value != null)
            {
                var runner = new ValidatorRunner(new CachedValidationRegistry());
                if (!runner.IsValid(result.Value))
                {
                    var summary = runner.GetErrorSummary(result.Value);
                    foreach (var invalidProperty in summary.InvalidProperties)
                    {
                        foreach (var error in summary.GetErrorsForProperty(invalidProperty))
                        {
                            bindingContext.ModelState.AddModelError(bindingContext.ModelName + "." + invalidProperty, error);
                        }
                    }
                }
            }
 
            return result;
        }
    }

And an object to validate:

    using Castle.Components.Validator;
 
    public class CreateUser
    {
        [ValidateNonEmpty("Please enter user name.")]
        public string UserName { get; set; }
        [ValidateNonEmpty("Please enter password.")]
        public string Password  { get; set; }
        [ValidateEmail("Email is not valid.")]
        [ValidateNonEmpty("Please enter email address.")]
        public string Email { get; set; }
    }

And an action to use the object:

        public ActionResult CreateUser(CreateUser createUser)
        {
            if (ViewData.ModelState.IsValid)
            {
                ViewData["Message"] = "Done.";
            }
 
            return View();
        }

Please note that, when the action is invoked, parameter is already validated. We just check ViewData.ModelState.IsValid and act accordingly.

Next, we'll tell the MVC engine to bind CreateUser objects through ValidatingModelBinder, in Application_Start() of Global.asax.cs:

        ModelBinders.Binders.Add(typeof(CreateUser), new ValidatingModelBinder());

So, whenever the engine is bindign to a CreateUser, our binder will execute (and validate) the object. Finally, code below for the view:

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <%if (ViewData["Message"] != null)
      {%>
        <%=ViewData["Message"]%>
    <%} %>
    <%=Html.ValidationSummary() %>
    <form method="post" action="/Home/CreateUser">
        User name: <br />
        <%=Html.TextBox("CreateUser.UserName")%>  <%=Html.ValidationMessage("CreateUser.UserName", "*")%><br />
        Password: <br />
        <%=Html.Password("CreateUser.Password")%> <%=Html.ValidationMessage("CreateUser.Password", "*")%><br />
        Email: <br />
        <%=Html.TextBox("CreateUser.Email")%> <%=Html.ValidationMessage("CreateUser.Email", "*")%><br />
        <input type="submit" value="Submit" />
    </form>
</asp:Content>

Here's the result: