I’m working on an ASP.NET MVC app (using MVC3 RC2). Say I have 2 entities, Product and Category. A Category must have a CategoryTitle, which is denoted via metamodel attributes like so:
public class CategoryModel
{
public int CategoryID { get; set; }
[Required("{0} is required.")]
public int CategoryTitle { get; set; }
}
There is also a relationship such that each Product has an association with Category. When searching Products, users must be able to filter the results by selecting a Category from a drop-down HTML select list. I’ve tried different ways of doing this, and the following seems to promote the most code reuse:
public class SearchModel
{
public CategoryModel Category { get; set; }
public string Keyword { get; set; }
}
public class ProductController
{
public ActionResult Search(SearchModel searchModel)
{
if (ModelState.IsValid)
{
// logic to return view with viewmodel
}
return HttpNotFound();
}
}
In the view, a drop-down list is rendered using the SearchModel, and it sends requests via HTTP GET in the form of /Product/Search?Keyword=my+keywords&Category.CategoryID=69. The SearchModel object is populated as intended, creating a new CategoryModel with CategoryID == 69.
The problem is that the ModelState.IsValid always returns false, since the Category.Title is null. What is the appropriate way to do this in ASP.NET MVC? Do I have to resort to creating a different SearchModel that doesn’t have a CategoryModel instance?
The proper way to do this is to use view models instead of your models to and from the views. View models are classes which are specifically tailored to the needs of a given view: they contain only the properties required for the view and the validation attributes in the context of the given view. Thus you might have multiple view models for the same model. To map between the model and the view models you could use AutoMapper.