Validating Nested ViewModels

I have two ViewModels (simplified):

public class ParentViewModel { public ParentViewModel { Content = new ChildViewModel(); } public ChildViewModel Content { get; set, } } public class ChildViewModel { [Required] public string Name1 { get; set, } [Required] public string Name2 { get; set, } } 

And the following controller post-control action:

 [HttpPost] public ActionResult Create(ParentViewModel viewModel) { if (ModelState.IsValid) { // process viewModel -> write something into database return RedirectToAction("Index"); } return View(viewModel); } 

Now I send the following form values ​​to the body of the mail request to the URL corresponding to this action (manually in Fiddler Request Builder):

  • Content.Name1 = X

    This works great, the Name1 property Name1 populated in viewModel.Content , Name2 is null , and the model state is invalid because Name2 is required. Therefore, the check is not performed as expected.

  • Xontent.Name1 = X or Name1 = X or whatever is associated with viewModel

    Now viewModel.Content not null (because I instantiate it in the constructor), but all the properties of Name1 and Name2 are null . It is expected. What I did not expect is that the state of the model is valid, so it passes the test (leading to database exceptions later because there are columns with a non-empty value).

How can I improve this code so that validation also works in the second case?

I did three experiments:

  • I deleted the Content instance in the ParentViewModel constructor, then Content is null in the second example above, but validation is still ongoing.

  • I added the [Required] attribute to the Content property (but did not delete the Content instance in the ParentViewModel constructor). This has no effect, the described behavior of the two above tests is the same.

  • I added the [Required] attribute to the Content property and deleted the Content instance in the ParentViewModel constructor. This seems to work the way I want: in the second test, Content is null , and the validation fails due to the [Required] attribute. It will look like this:

     public class ParentViewModel { [Required] public ChildViewModel Content { get; set, } } public class ChildViewModel { [Required] public string Name1 { get; set, } [Required] public string Name2 { get; set, } } 

In conclusion, I would like to conclude that the creation of the parent Content property in the ParentViewModel constructor is the source of the problem and that the picker itself must create instances of the child properties (or not, if the request is in the field) in order to have the correct working check on the server side .

I have an instance of a child property in several constructors of other views and still have not noticed this problem. So, is this generally bad practice? Are there other ways to solve the problem?

+8
validation asp.net-mvc asp.net-mvc-3
source share
2 answers

The third solution is fine:

 public class ParentViewModel { [Required] public ChildViewModel Content { get; set, } } public class ChildViewModel { [Required] public string Name1 { get; set, } [Required] public string Name2 { get; set, } } 

I am using it now in several places and have not noticed any problems.

0
source share

ModelState.IsValid tells you if any model errors have been added to ModelState.

The default binder will add some errors for base type conversion problems, such as passing a non-number for something that is "int". You can populate ModelState more fully based on any validation system you use. I would suggest exploring data annotations to validate ViewModels, as it works well.

This syntax may be incorrect or old. ModelState.AddModelError ("key", exception)

paraphrased from What is ModelState.IsValid valid for ASP.NET MVC in NerdDinner?

0
source share

All Articles