views:

275

answers:

1

I'm trying to setup xVal with an ASP.NET MVC 2 Preview 1 project. I'm basically following the example at http://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/ to the letter (server-side only, so far).

I have annotated a BlogPost entity, and here is the Post action:

[HttpPost]
public ActionResult Index(BlogPost b)
{
    try
    {
        _blogService.Insert(b);
    }
    catch (RulesException ex)
    {
        ex.AddModelStateErrors(ModelState, "");
    }

    return (View(b));
}

And here's the service method:

public void Insert(BlogPost post)
{
    var errors = DataAnnotationsValidationRunner.GetErrors(post);
    if(errors.Any())
    {
        throw new RulesException(errors);
    }

    _blogRepo.Insert(post);
}

(Note that the DataAnnotationsValidationRunner is verbatim from the example blog post). When I submit a totally invalid BlogPost form, I get this list of validation errors:

  • A value is required.
  • Please enter a title
  • Please enter a posted date
  • Please enter some content
  • Please enter a title
  • Please enter a posted date
  • Please enter some content

I don't even know what the first message is for, but as you can see, the other errors are appearing twice. What am I doing wrong? Or is this a problem with MVC V2?

+1  A: 

Starting in ASP.Net MVC 2 Preview 1 we now get DataAnnotation validation support out of the box, so I guess your issue is that when the ModelBinder logic runs it is applying the DataAnnotation rules:

public ActionResult Index(BlogPost b) //Create BlogPost object and apply rules

and then with your XVal logic you are requesting the check again:

var errors = DataAnnotationsValidationRunner.GetErrors(post);

This is backed up by the fact they are repeated in the same order.

Your code would have worked fine in version 1 of MVC as public ActionResult Index(BlogPost b) would not have run the DataAnnotation rules. I have not read anywhere if it is possible to turn off the new DataAnnotation logic and just use XVal.

There is more information about this on Scott's post able preview 1

To find out what the first item is run debug and check what errors are on the ModelState, as this will tell you what property on the object the errors are related to.

[HttpPost]
public ActionResult Index(BlogPost b)
{
    try
    {
        _blogService.Insert(b); //Add breakpoint here and check ModelState
    }
    catch (RulesException ex)
    {
        ex.AddModelStateErrors(ModelState, "");
    }

    return (View(b));
}
Nick Clarke
Yep, that's it. I actually didn't think the Annotation stuff would work that easily, wow. Anyway, the other error was because I didn't set the Id value to use a private set (NHibernate POCO). Thanks very much!
mgroves