ASP.NET MVC Model/ViewModel Validation

asp.net-mvcdata-annotationsvalidationviewmodel

I have model classes in Linq-to-Sql with partial classes marked with data annotation attributes and a reference to xVal.

When I bind a view directly to a model everything works great, both the JS generated by xVal and server side double check.

Many of my views don't take input to one specific model, so I am setting up view model classes. Instead of exposing an entire model instance I expose properties into the model that I allow/need to be set by the view.

// foo model 
public class Foo {
    public string FooField { ... }
    public Bar Bar { ... }
}

// bar model, where bar is a parent relationship of foo in the db
public class Bar {
    public string BarField { ... }
}

// view model stuff
public class FooViewModel {
    private Foo foo;

    public FooViewModel() {
        foo = new Foo() { Bar = new Bar() };
    }

    public Foo Model {
        get { return foo; }
        set { foo = value; }
    }

    public string BarField { 
        get { return foo.Bar.BarField; }
        set { foo.Bar.BarField = value; }
    }

    public string ExtraViewModelField {
        get; set; 
    }
}

This approach populates the view model class correctly and the repository can populate the record correctly.

It doesn't pull through the validation at all though. I have looked at the client code emitted and the validation array is empty for xval. Additionally, the server side check for IsValid is always true.

Can I have the data annotations pull though the properties of view model for validation like this, or should I be doing this another way?

Best Answer

If you use partials, and pass in the subtype, you still need to qualify. See as follows:

<%@ Control Language="C#" 
                   Inherits="System.Web.Mvc.ViewUserControl<MvcWeb.Models.OrderDetail>" %>

<% using (Html.BeginForm()) { %>

    <fieldset>
        <legend>Fields</legend>
            <%= Html.Hidden("OrderId", Model.OrderId) %>
            <%= Html.Hidden("ProductId", Model.ProductId)%>
        <p>
            <label for="Quantity">Quantity:</label>
            <%= Html.TextBox("OrderDetails.Quantity", Model.Quantity)%>
            <%= Html.ValidationMessage("OrderDetails.Quantity", "*") %>
        </p>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

Notice that the type is OrderDetails, but I'm still prefixing that to deal with validation messages.