如何使用视图模型作为控制器方法属性更新特定的数据库条目

How do I update a specific database entry with a view model as controller method attribute

我的网站中有一个输入 table,它连接到一个视图模型。在控制器方法中,我将此视图模型传递给控制器​​,反之亦然,这意味着控制器使用数据库中的数据填充视图模型,视图 returns 填充用户可能输入的表单数据的视图模型.

问题是,一旦视图接收到视图模型对象,数据库中的 "ID" 属性就不再存在。调用 Post 方法时,无法知道必须更新哪个数据库条目。

我的问题是:当我将视图模型传递给控制器​​方法时,如何更新特定的数据库条目?

示例控制器方法:

[HttpPost]
public ActionResult method(ViewModel vm)
{
    DataContext.Context.Where(x => x.ID == vm.Object.ID) // this is where vm.Object.ID always returns "0", not the actual ID from the database entry
    Context.SaveChanges();
    return View(vm);
}

如果您需要更多信息,请告诉我。此外,使用 jquery 不是该项目的可行选择。非常感谢您的帮助!

编辑:

查看:

@model MyANTon.ViewModels.Q4_Answer_VM


@{
    ViewBag.Title = "myANTon Anforderungserfassung";
    ViewBag.HideNavBar = false;
}


@using (Html.BeginForm())

{
    <div class="container">
        <div class="jumbotron">

            <hr />
            <table class="grid" id="datatable">
                <tr>
                    <th>Nr.</th>
                    <th>Last</th>
                    <th>Quelle</th>
                    <th>Ziel</th>
                    <th>Frequenz [/h]</th>
                    <th>Abstand [m]</th>
                    <th></th>
                    <th></th>

                    @{int i = 1; }

                    @for  (var a = 0; a < Model.Matrix.Count; a++)
                    {
                    <tr>
                        <td>@(i++)</td>
                        <td>@Html.TextBoxFor(x => Model.Matrix[a].Load)</td>
                        <td>@Html.TextAreaFor(x => Model.Matrix[a].Source)</td>
                        <td>@Html.TextAreaFor(x => Model.Matrix[a].Goal)</td>
                        <td>@Html.TextAreaFor(x => Model.Matrix[a].Frequency)</td>
                        <td>@Html.TextAreaFor(x => Model.Matrix[a].Distance)</td>
                        <td><input type="submit" name="+" class="btn btn-default" value="+" /></td>
                        <td><input type="submit" class="btn btn-default" value="-" /></td>

                    </tr>
                    }
                </table>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" class="btn btn-default" name="Speichern" value="Speichern" />
                        <input type="submit" class="btn btn-default" value="Speichern und weiter" />
                        <input type="button" class="btn btn-default" value="Weiter zu Schritt 5" onclick="@("window.location.href='" + @Url.Action("Q_Fifthpage", "Home") + "'");" />
                    </div>   
                </div>  
            </div>
        </div>
 }

获取方法:

    [HttpGet]
        public ActionResult Q_FourthPage()
        {
            // get current Questionnaire ID
            int CurrentQstID = Convert.ToInt32(Session["qstid"]);

            // create vm object. Capacity is a column in the table.
            var Q4ViewModel = new ViewModels.Q4_Answer_VM();

            // look for existing input data columns for this questionnaire in db
            if (db.Capacities.Any(x => x.Questionnaire_ID == CurrentQstID))
            {
                // answers exist
                Q4ViewModel.Matrix.AddRange(db.Capacities.Where(x => x.Questionnaire_ID == CurrentQstID));

            }
            else
            {
                // new capacity matrix
                Q4ViewModel.TMatrix = db.QuestionTexts.Where(x => x.ID == 21).FirstOrDefault();
                Q4ViewModel.Matrix = new List<Models.Capacity>();
            }

            var tmpcapacity = new Models.Capacity();
            tmpcapacity.Questionnaire_ID = Convert.ToInt32(Session["qstid"]);

            Q4ViewModel.Matrix.Add(tmpcapacity);
            db.Capacities.Add(tmpcapacity);
            db.SaveChanges();
            return View(Q4ViewModel);
        }

POST方法:

    [HttpPost]
        public ActionResult Q_FourthPage(ViewModels.Q4_Answer_VM vm)
        {
            int currentQst = Convert.ToInt32(Session["qstid"]);

            if (Request.Form["+"] != null)
            {

                var tmpcapacity = new Models.Capacity();
                tmpcapacity.Questionnaire_ID = currentQst;
                vm.Matrix.Add(tmpcapacity);

                db.Capacities.Add(tmpcapacity);
                db.SaveChanges();

                return View(vm);
            }

            if (Request.Form["Speichern"] != null)
            {
            // save data
                if (!ModelState.IsValid) return View("~/Views/Shared/Error.cshtml");

                var tmpcapacity = new Models.Capacity();

                for (var a = 0; a < vm.Matrix.Count; a++)
                {
                    var current = vm.Matrix[a];
                    current.ID = vm.Matrix[a].ID;
                    if (db.Capacities.Any(x => x.ID == current.ID))
                        // if clause never triggers true
                        // vm does not contain capacity ID
                    {
                        // column exists and is changed (or not)

                        tmpcapacity.Distance = vm.Matrix[a].Distance;
                        tmpcapacity.Frequency = vm.Matrix[a].Frequency;
                        tmpcapacity.Source = vm.Matrix[a].Source;
                        tmpcapacity.Goal = vm.Matrix[a].Goal;
                        tmpcapacity.Load = vm.Matrix[a].Load;
                        Models.Capacity c = db.Capacities.Where(x => x.ID == current.ID).FirstOrDefault();
                        c = tmpcapacity;
                        db.SaveChanges();

                    }
                    else
                    {
                        // new column
                        tmpcapacity.Distance = vm.Matrix[a].Distance;
                        tmpcapacity.Frequency = vm.Matrix[a].Frequency;
                        tmpcapacity.Source = vm.Matrix[a].Source;
                        tmpcapacity.Goal = vm.Matrix[a].Goal;
                        tmpcapacity.Load = vm.Matrix[a].Load;
                        tmpcapacity.Questionnaire_ID = currentQst;

                        db.Capacities.Add(tmpcapacity);
                        db.SaveChanges();
                    }

                }
                db.SaveChanges();
            }    
            return View(vm); 
        }

如果您想 "save" object ID 并在 post 发生时取回它,您需要使用 .HiddenFor() 将其存储到隐藏字段中HTML 助手 - 类似这样的东西:

@using (Html.BeginForm())
{
    @Html.HiddenFor(m => m.Object.Id);

    <div class="container">
        <div class="jumbotron">

然后,在你的 POST 上,你应该在你的 post body 中取回 Object.ID 并且你应该能够分辨出哪个 object这是为了.

如果需要将ID绑定到Model上,那么在使用Razor时需要在表单下使用hidden filed。

@Html.HiddenFor(model => model.Id)

更多详情

@using (Html.BeginForm("method", "ControllerName", FormMethod.Post))
{
@Html.HiddenFor(Model=>Model.ID)

<div class="form-group">
    @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
    </div>
</div>
<div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <input type="submit" class="btn btn-default" value="Button" />
    </div>
</div>
}

现在您可以在您的控制器操作方法中访问 ID。