totalnoob
totalnoob

Reputation: 2741

validation on model or view model?

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);
 }

Upvotes: 0

Views: 2048

Answers (1)

galdin
galdin

Reputation: 14074

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)

Upvotes: 6

Related Questions