0

I'm reading tutorials and trying to get used to using ViewModels and Validation. I'm unsure as to whether the validation goes on the main Model or the View Model, I'd assume it'd be on the ViewModel. But it doesn't seem to make sense to add the validation on the ViewModel if I'm trying to inherit a class property so I left it on the model itself but the errors aren't showing up. Perhaps the Models are inefficient and need to be rearranged a bit?

NameModel

 public class name {
      [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 3)]
      public string first { get; set; }
      public string middle  { get; set; }
      [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 3)]
      public string last  { get; set; }
      public string otherstuffnotneededontheview { get; set; }
 }

RegisterViewModel

 public class RegisterViewModel {
     public name fname { get; set; }
     public name lname { get; set; }
 }

View

 @model Project.ViewModels.RegisterViewModel

 @using (Html.BeginForm())
 {
     <label>
     @Html.TextBoxFor(model => model.fname.first)
     @Html.ValidationMessageFor(model => model.fname.first)
     </label>

     <label>
     @Html.TextBoxFor(model => model.lname.last)
     @Html.ValidationMessageFor(model => model.lname.last)
     </label>
     <input type="submit" />
 }

Controller

 public ActionResult Register()
 {
      RegisterViewModel model = new RegisterViewModel();
      return View(model);
 }

 [HttpPost]
 public ActionResult Register(RegisterViewModel model)
 {
       return View(model);
 }
0

1 Answer 1

6

All validation needs to be done on the ViewModel.

In your case the RegisterViewModel is the data representation of the View associated public ActionResult Register(), which means, the view returns a RegisterViewModel object not a name object.

ModelState.IsValid checks validates the view's input [Register.cshtml] against the type it is bound to [RegisterViewModel not name]

So only the attributes applied to the RegisterViewModel will be Validated.

So you need to perform validation in the ViewModel.

This in-turn provides you additional flexibility of being able to use different validation rules for different ViewModels (though the ViewModels are bound to the same underlying Model)

EDIT: (with code suggestion)

No validation rules are applied to the Model properties

public class name {
      public string first { get; set; }
      public string middle  { get; set; }
      public string last  { get; set; }
      public string otherstuffnotneededontheview { get; set; }
 }

They are applied in the ViewModel instead

public class RegisterViewModel {
     [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 3)]
     public string fname { get; set; }
      [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 3)]
     public string lname { get; set; }
 }

This change should be pretty much enough (guessing you're properly binding RegisterViewModel to name)

Sign up to request clarification or add additional context in comments.

1 Comment

You state "This in-turn provides you additional flexibility of being able to use different validation rules for different ViewModels (though the ViewModels are bound to the same underlying Model)". What use-case would you want different validation rules for different ViewModels? Maybe the example model from the OP is a bad example, but when would ever want to allow the user to set FName to something greater than 50 chars or less than 3 chars?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.