Search code examples
asp.net-mvc-4modelmodelstate

ModelState.IsValid == false, although all model values are inserted


today I have the problem, that after i inserted all data to a formular to create a new Product, the programm say that ModelState.IsValid==false.

When i look into the modelState during debugging there is a Error on field 0. The error: "The CuId field is required".

To prevent that i set CuId right in the Creat POST action like so in the ProductController.cs:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Product product)
    {
        int lastcu = db.Customers.Max(l => l.Id);
        product.CuId = last; 

        if (ModelState.IsValid)
        {
            db.Products.Add(product);
            db.SaveChanges();
            return RedirectToAction("Create", "NewIssue");
        }


        return View(product);
    }

But again it sets the same error. My view looks like that. Actually the model.CuId should already set there:

@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)

<fieldset>
    <legend>Product</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.CuId, "Customer")
        @ViewBag.Cuname    
        @Html.HiddenFor(model => model.CuId, new { id = "lastcu" })
     </div>

My GET Controller looks like this:

 public ActionResult Create()
    {
        int lastcu = db.Cu.Max(l => l.Id);
        //gives the id a Name
        var lastcuname = db.Customers.Find(lastcu).Name;
        //show to User by creating the product
        ViewBag.Cuname = lastcuname;
        ViewBag.CuId = lastcu;

        return View();
    }

When I look in debug mode into the values of the model product, all fields are filled (also CuId) except of the the foreign key what is bind to the product.CuId and the Id of the product what is set automatically from the database.

Hopefully you can help me. Thanks in advance.


Solution

  • As for the first part of your question, ModelState is populated by the DefaultModelBinder when the method is first called. If property CuId has the [Required] attribute and its value is not posted back, then an error is added to ModelState and therefore ModelState.IsValid is false. Just setting a property of your model does not remove ModelState values.

    As for the second part of your question, your not passing you model to the view in the GET method so @Html.HiddenFor(m => m.CuId) generates a hidden input with no value (because the value of model.CuId is null or its default). All you currently doing is passing some values to the view using ViewBag (not good practice) which you never even use. Instead, pass the model to the view as follows.

    public ActionResult Create()
    {
        int lastcu = db.Cu.Max(l => l.Id);
        var lastcuname = db.Customers.Find(lastcu).Name;
        // Initialize a new instance of the model and set properties
        Product model = new Product()
        {
          CuId = lastcu,
          Cuname = lastcuname // assume this is a property of your model?
        };
        return View(model); // return the model
    }
    

    Side note: @Html.LabelFor(model => model.CuId, "Customer") generates a html <label> which is an accessibility element. Clicking on it sets focus to its associated form control. But you don't have an associated form control (just a hidden input which cannot receive focus)