locked
Entity Not Updating in Database RRS feed

  • Question

  • User438705957 posted

    I am following a pattern in an MVC controller to avoid overposting while updating a record.
    I have left certain fields out of the View because I don't want the user to update these fields.
    I then want to update the model using only the whitelisted fields.

    In the controller I have an action that uses TryUpdateModel for this purpose.
    It does not fail, and makes the call to update the context successfully.

    The problem is, it just doesn't update the record in the database.

    Here is the code.

    [HttpPost, ActionName("Edit")]
            [ValidateAntiForgeryToken]
            public ActionResult EditPost(int? id)
            {
                if (id == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
               
                using (var dbContext = new CACS_GNS_DataContext())
                {
                    var userToUpdate = dbContext.Users.Find(id);
                    if (TryUpdateModel(userToUpdate, "",
                        new string[] { "User_First_Name,User_Last_Name,User_Email,Active,Role_Id,Position_Id" }))
                    {
                        try
                        {
                            dbContext.SaveChanges();
                            return RedirectToAction("Index");
                        }
                        catch (DataException dex)
                        {
                            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
                        }
                    }
                    return View(userToUpdate);
                }
            }

    The pattern I am using works for another entity in the model withut a problem.

    Stumped.

    Thursday, April 5, 2018 12:30 AM

All replies

  • User1120430333 posted

    Maybe, you are not saving the data to the database that you think you are saving it to.

    Thursday, April 5, 2018 1:01 AM
  • User-166373564 posted

    Hi Madog,

    it just doesn't update the record in the database.

    When using the TryUpdateModel method, it will update the fields from user input in the posted form data. So I suppose perhaps the issue is related that you can't get the user entered form data. You could check the form data through the FormCollection, Parameters or the Strongly typed model. More details, please check the following article:

    https://www.codeproject.com/Articles/758458/Passing-Data-View-to-Controller-Controller-to-View 

    If still not working, I suggest you post the view code, might be it is easier for us to help you.

    Best regards,
    Angie

    Thursday, April 5, 2018 2:53 AM
  • User438705957 posted

    Thanks DA924,

    Suspected that myself, checked it all out, and it should be updating the database for the context.
    it is creating a User successfully.

    Thursday, April 5, 2018 3:16 AM
  • User438705957 posted

    Thanks Angie,

    I read that article and it appears in my case the model binder is using field names from the form to bind to corresponding parameter names in the controller action.

    I have modified the Edit action to include all the fields I wish to update

    public ActionResult EditPost(int? User_id, string User_First_Name, string User_Last_Name, string User_Email, bool Active,int Role_Id,int Position_Id)

    This is the same field name list as used in the TryUpdateModel statement.
    I examined everyone of these fields after hitting the controller and they match what  I changed in the UI.
    In addition, I could see the posted form data with the changed values in the request body thru developer tools.
    It still does not update to the new value.

    According to what I have read, reading the existing entity and calling TryUpdateModel to update fields (from posted form data) causes Entity Framework's automatic change tracking to set the Modified flag on the entity.

    I believe in my case, EF is not setting the Modified flag properly.

    The view is posted here as you requested.

    @model MVC1.Models.User
    
    @{
        ViewBag.Title = "Edit";
    }
    
    <h2>Edit</h2>
    
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        
        <div class="form-horizontal">
            <h4>User</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            @Html.HiddenFor(model => model.User_Id)
    
            <div class="form-group">
                @Html.LabelFor(model => model.User_First_Name, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.User_First_Name, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.User_First_Name, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.User_Last_Name, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.User_Last_Name, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.User_Last_Name, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.User_Email, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.User_Email, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.User_Email, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Active, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    <div class="checkbox">
                        @Html.EditorFor(model => model.Active)
                        @Html.ValidationMessageFor(model => model.Active, "", new { @class = "text-danger" })
                    </div>
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Role_Id, "Role_Id", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.DropDownList("Role_Id", null, htmlAttributes: new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.Role_Id, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Position_Id, "Position_Id", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.DropDownList("Position_Id", null, htmlAttributes: new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.Position_Id, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Save" class="btn btn-default btn-success" />
                    <input type="button" value="Cancel" class="btn btn-default btn-danger" onclick="location.href='@Url.Action("Index","Users")';" />
                </div>
            </div>
    
        </div>
    }
    
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>


    Thursday, April 5, 2018 3:42 AM
  • User438705957 posted

    Update......I solved it using UpdateModel instead of TryUpdateModel.
    Why it worked and TryUpdateModel didn't work is still a mystery.

    Here is the working code:

     [HttpPost, ActionName("Edit")]
            [ValidateAntiForgeryToken]
            public ActionResult EditPost(int? User_id, string User_First_Name, string User_Last_Name, string User_Email, bool Active,int Role_Id,int Position_Id)
            {
                if (User_id == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
               
                using (var dbContext = new CACS_GNS_DataContext())
                {
                    var userToUpdate = dbContext.Users.Find(User_id);
    
                    try
                    {
                        UpdateModel(userToUpdate);
    
                        if (ModelState.IsValid)
                        {
                            dbContext.SaveChanges();
                            return RedirectToAction("Index");
                        }
                        else
                        {
                            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
                        }    
                    }
                    catch (DataException dex)
                    {
                        
                        throw dex;
                    }                                           
                    
                    return View(userToUpdate);
                   
                }
            }

    Thursday, April 5, 2018 3:56 AM