1

I can't quite wrap my head around the model validation. Let's assume the following ViewModel:

public class UserEditViewModel
{
    public List<Role> AvailableRoles { get; set; }
    public string? SelectedRole { get; set; }   
}

The goal is to let the user select from a list of roles (think of a dropdown).

In the HttpGet I populate the list of available roles form a database like this:

UserEditViewModel uevm = new UserEditViewModel();
uevm.AvailableRoles = _db.Roles.ToList();

When I get the UserEditViewModel back from the HttpPost event, it will have an invalid model state:

if (ModelState.IsValid) { ...}

The validation will state that while the SelectedRole is valid, the list of available roles is NOT valid.

Now I can think of multiple solutions to this problem but am unsure on how to proceed:

  • I could create a custom constructor for the UserEditViewModel which populates the AvailableRoles list from a database. But this means that I will need to pass a reference to the database context into the UserEditViewModel
  • I could simply ignore the ModelState because I know it is invalid? What would I lose in this case?

I had some hope hat the Bind property would maybe help like this:

public ActionResult EditUser([Bind(include:"SelectedRole")] UserEditViewModel editViewModel, string id)

but it appears that ModelState is still invalid even if I specify I only want the SelectedRole.

This leads me to the ultimate question: What is the correct way to approach this issue?

Jackdaw
  • 7,626
  • 5
  • 15
  • 33
Tom L.
  • 932
  • 2
  • 9
  • 30
  • Did you applied any `DataAnnotations` attributes to properties in the `UserEditViewModel` class? – Jackdaw Feb 10 '22 at 08:35
  • I did not. Is there an annotation where I can specify it shouldn't be checked during ModelState validation? – Tom L. Feb 10 '22 at 08:47
  • I asked this just to understand if you are doing any validation on the client side. So, it's seems should work. You can try add `ModelState.Remove(" AvailableRoles");` before `if (ModelState.IsValid) {...}` to remove validation of this property. If this will not help add code of the view to the post, please. – Jackdaw Feb 10 '22 at 08:58
  • Are you saying it should not be necessary to do anything at all? Should the ModelState be Valid for such a setup? – Tom L. Feb 10 '22 at 09:01
  • No. Of course you should validate the `SelectedRole` value on the server side. But it's hard to understand what values in the current context can make the model not valid. Show more you code please. Sorry, there is type in my comment above: should be without the space `ModelState.Remove("AvailableRoles");` – Jackdaw Feb 10 '22 at 09:06
  • I can see that it's not valid because of he AvailableRoles item. I just changed the List AvailableRoles to a nullable type (List? AvailableRoles) and it appears that the validation issue is gone. Could that really be the issue here? – Tom L. Feb 10 '22 at 09:09
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/241896/discussion-between-jackdaw-and-tom-l). – Jackdaw Feb 10 '22 at 09:10
  • Does this answer your question? [Disable Required validation attribute under certain circumstances](https://stackoverflow.com/questions/5367287/disable-required-validation-attribute-under-certain-circumstances) – Jackdaw Feb 10 '22 at 09:18

1 Answers1

2

Try to apply [ValidateNever] attribute to remove validate an unused property on the server side:

public class UserEditViewModel
{
    [ValidateNever]
    public List<Role> AvailableRoles { get; set; }
    public string? SelectedRole { get; set; }   
}

From the documentation:

Indicates that a property or parameter should be excluded from validation. When applied to a property, the validation system excludes that property. When applied to a parameter, the validation system excludes that parameter. When applied to a type, the validation system excludes all properties within that type.

But if it's necessary to avoid validation only when returning model data from a specific view use ModelState.Remove("AvailableRoles"); before if (ModelState.IsValid) {...}.

Jackdaw
  • 7,626
  • 5
  • 15
  • 33