Mohammad
Mohammad

Reputation: 71

satisfying the validation before checking the validation

suppose I have the following class

class A
{
  [Required]
  public string Name {get; set;}
  [Required]
  public string NickName {get; set;}
  [Required]
  public string UserId {get; set;}
}

and from the form I am passing only the Name and NickName to controller and before checking the model state simply I assign the user id to the UserId property as below

    [HttpPost]
    public IActionResult Save(A model)
    {
        model.UserId = User.GetLoggedInUserId<string>();
        if (!ModelState.IsValid)
        {
           return View(model);
        }        
    }

even though I have assign the user id before checking the model state it still returns the validation state false and complaining the for the user id. one way to come out of this problem is to create a view model which makes things more complex, because of assigning the values from view model to class it self. any idea how to solve this.

Note: the question is not only for the User Id in the class there maybe other properties as well that may not be passed from the form to controller and the values maybe assigned to them from controller

Upvotes: 0

Views: 318

Answers (3)

Zhi Lv
Zhi Lv

Reputation: 21421

You could try to remove the 'UserId' from the model validation before calling ModelState.IsValid. Code like this:

    [HttpPost]
    public IActionResult CreateA(A a)
    {
        var state1 = ModelState.IsValid;  // false
        ModelState.Remove("UserId");      //using Remove method to remove the specified object from the model-state dictionary.
        var state2 = ModelState.IsValid;  // true
        
        a.UserId = "SN1001";
          
        if (ModelState.IsValid)
        {
            var data = a.UserId;
        }
        return RedirectToAction(nameof(Index));
    }

The screenshot as below:

enter image description here

Besides, you could also try to use the TryValidateModel() method to validate the model again in the controller, code like this:

    [HttpPost]
    public IActionResult CreateA(A a)
    {
        var state1 = ModelState.IsValid;  // false 
        
        ModelState.Remove("UserId");

        a.UserId = "SN1001";

        if (!TryValidateModel(a, nameof(a)))
        { 
            var state2 = ModelState.IsValid;              
        }

        if (ModelState.IsValid)
        {
            var data = a.UserId;
        }
        return RedirectToAction(nameof(Index));
    }

The result like this:

enter image description here

Reference: Model State Rerun validation

Edit

[Note] If the ModelState.IsValid is false first, before rerun validation using the TryValidateModel method, we have to remove the error from the ModelState.

Upvotes: 3

Giorgos Betsos
Giorgos Betsos

Reputation: 72175

You can also pass the value of UserId field using a hidden field with a default value, like:

@Html.HiddenFor(m => m.UserId, new { @Value = User.Identity.Name });

Upvotes: 1

Athanasios Kataras
Athanasios Kataras

Reputation: 26372

This answer might help What does ModelState.IsValid do?

ModelState.IsValid indicates if it was possible to bind the incoming values from the request to the model correctly and whether any explicitly specified validation rules were broken during the model binding process.

There is no way to solve this. If you don't need this validation, then remove it altogether with the attributes and add the appropriate value handling logic with code.

The isValid will just validate the state on binding time and that's that.

Upvotes: 0

Related Questions