adam78
adam78

Reputation: 10078

Asp MVC 5 - ModelState is Invalid?

I have the following view model:

public class CreateCaseViewModel
{
    [Required]
    public string Subject { get; set; }

    [Required]
    [DisplayName("Post Content")]
    [UIHint("ForumEditor"), AllowHtml]
    [DataType(DataType.MultilineText)]
    public string PostContent { get; set; }

    // some other dropdown properties

}

The following controller action:

 [HttpPost]
 [ValidateAntiForgeryToken]
 [ValidateInput(false)]
 public ActionResult Create(CreateCaseViewModel viewModel, FormCollection collection)
 {

        // Re-populate dropdowns 
        viewModel.Categories = _unitOfWork.CategoryRepository.GetCategories();


        viewModel.Subject = collection["Subject"];
        viewModel.PostContent = collection["Description"];

        try
        {
            if (ModelState.IsValid)
            {
                // Do stuff
            }
        } 
        catch (DataException  dex  )
        {
           throw new ApplicationException("Something :", dex);
        }

        return View(viewModel);    

 }

I am manually assigning the value to PostContent from a value in FormCollection as you can see from code above. However I still keep getting modelstate is invalid - I'm returned back to the view with the validation error saying `The Post Content field is required'

Why is modelstate invalid?

Upvotes: 1

Views: 2903

Answers (2)

Shyju
Shyju

Reputation: 218882

When you submit the form the model binder will read the posted request data and map it to your method parameter. After that model validation framework will do the validation. It does not look at your FormCollection for doing this. So in your case, your model validation is failing because as per your view model it is expecting a value for PostContent property and it is not available there. Your action method code where you are setting the value of it gets executed later ( by this time model validation already occurred).

Your options are, either standardize the input element name with your view model property name (rename the PostContent to Description or vice versa)

public class CreateCaseViewModel
{
    [Required]
    public string Subject { get; set; }

    [Required]
    [DisplayName("Post Content")]
    [UIHint("ForumEditor"), AllowHtml]
    [DataType(DataType.MultilineText)]
    public string Description { get; set; }    

}

Now let the model binder maps the request body to your view model parameter. Remove the manual assignment from the FormCollection in your action method

Or you can probably create a new custom model binder which does the custom mapping for you (same as what you did in your action method).

I would go with option one. Let the default model binder takes care of it.

Upvotes: 1

Philip Smith
Philip Smith

Reputation: 2801

The model is validated before it is passed to your controller action. Modifying the model does not change that.

You need to call ModelState.Clear() followed by Controller.TryValidateModel(model) to re-validate the model and reset the IsValid property.

Upvotes: 1

Related Questions