views:

339

answers:

4

I have an MVC2 Application that uses MVVM pattern. I am trying use Data Annotations to validate form input.

In my ThingsController I have two methods:

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

    public ActionResult Details(ThingsViewModel tvm)
    {
    if (!ModelState.IsValid) return View(tvm);

        try
        {
Query q = new Query(tvm.Query);
            ThingRepository repository = new ThingRepository(q);

tvm.Things = repository.All();                
return View(tvm);
        }
        catch (Exception)
        {
            return View();
        }
    }

My Details.aspx view is strongly typed to the ThingsViewModel:

<%@ Page Title="" 
         Language="C#" 
         MasterPageFile="~/Views/Shared/Site.Master"        
         Inherits="System.Web.Mvc.ViewPage<Config.Web.Models.ThingsViewModel>" %>

The ViewModel is a class consisting of a IList of returned Thing objects and the Query string (which is submitted on the form) and has the Required data annotation:

public class ThingsViewModel
{
    public IList<Thing> Things{ get; set; }

    [Required(ErrorMessage="You must enter a query")]
    public string Query { get; set; }
}

When I run this, and click the submit button on the form without entering a value I get a YSOD with the following error:

The model item passed into the dictionary is of type 
'Config.Web.Models.ThingsViewModel', but this dictionary 
requires a model item of type 
System.Collections.Generic.IEnumerable`1[Config.Domain.Entities.Thing]'.

How can I get Data Annotations to work with a ViewModel? I cannot see what I'm missing or where I'm going wrong - the VM was working just fine before I started mucking around with validation.

+1  A: 

I don't think the problem is with the validation.

Change this line;

tvm.Things = repository.All(); //Is this the Linq extension method 'All()'?

to this

tvm.Things = repository.ToList();

I don't know what this is or what it does;

new ThingRepository(q);

It takes a string parameter and returns some kind of Linq IQueriable or List? If that's returning something else it could be causing the problem.

Casey Burns
A: 

Do you have client-side validation enabled? It might even be a quick hacky-fix, but regarding the error message - it's tough to say without extra info. Could you post your View and the rendered Html? What does your route for Details look like? If you set a breakpoint at the start of the Details method, does it get hit when you click on the submit button?

Yakimych
A: 

It looks like you could just declare your ThingsViewModel like so:

public class ThingsViewModel: IEnumerable<Thing>

and then implement the interface as appropriate to access the Things list.

Bob
A: 

I think that ASP.NET MVC might be trying to map your view to the wrong controller. When you return the view you might need to specify the view file name you're trying to use.

return View("ViewName")

Paul Mendoza