将模型绑定与MVC 5中的表单发布混合?

时间:2016-11-29 14:59:36

标签: asp.net-mvc model-binding

是否可以启用模型绑定以及表单中的发布数据?

我有一个集合属性,我想在foreach循环中迭代以保存集合中的每个选定项目:

    <div class="form-group">
        @Html.LabelFor(m => m.Users, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @{
                List<ApplicationUser> allUsers = ViewBag.AllUsers;
                bool assigned;
            }
            <div>
                @foreach (var user in allUsers)
                {
//here I want to render all users, and only the users who are in the task, have a checked checkbox

                    assigned = Model.Users.Select(u => u.Id).Contains(user.Id);
                    <input type="checkbox" name="asndUsers" value="@user.Id" id="@user.Id" @Html.Raw(assigned ? "checked" : "") /> <label style="font-weight: normal;" for="@user.Id">@user.UserName</label><br />
                }
            </div>
        </div>
    </div>
//fields updated with model binding:
    <div class="form-group">
        @Html.LabelFor(m => m.Status, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(m => m.Status, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(m => m.Status)
        </div>
    </div>

这是编辑动作帖子方法:

[HttpPost, ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,Title,Description,DueDate,Status")] UserTask task, string[] asndUsers)
{
    if (ModelState.IsValid)
    {
        task.Users = new List<ApplicationUser>();
        foreach (var item in asndUsers)
        {
            var user = context.Users.Find(item);
            task.Users.Add(user);
        }
        context.Entry(task).State = EntityState.Modified;
        context.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(task);
}

它在我调试时有效,我看到新发布的数据已与绑定数据合并。 但是当请求重定向到索引视图时,编辑项目后没有变化,这是索引操作方法:

public ActionResult Index(int? taskId)
{
    var viewModel = new TasksUsers();
    viewModel.Tasks = context.Tasks.Include(x => x.Users);
    if (taskId != null)
    {
        viewModel.Users = viewModel.Tasks.Where(t => t.Id == taskId).Single().Users;
        ViewBag.Row = taskId;
    }
    return View(viewModel);
}

2 个答案:

答案 0 :(得分:1)

原始答案

  

更新相关实体的正确方法是先加载它们,   所以我使用了预先加载来重新定义传入的def f(x): return x class MyA(object): def f(self, x): return f(x) class MyB(MyA): def f(self, x): y = f(x) ... return y 参数   如下:

task
     

task = context.Tasks.Include(t => t.Users).Single(s => s.Id == task.Id); Note that `Find` can't be used with `Include` so I used

     

解决了更新用户实体的问题

这是错的, 正确的方法是使用显式绑定而不是隐式绑定(Single

答案 1 :(得分:0)

DbContext不再跟踪回发的任务。尝试在编辑操作中将任务Attach添加到DbSet:

    context.Tasks.Attach(task);
    if (task.Users == null) {
        task.Users = new List<ApplicationUser>();
    }
    foreach (var item in asndUsers) {
        var user = context.Users.Find(item);
        task.Users.Add(user);
    }
    // may be important because Attach() sets the State to 'Unchanged'?
    context.Entry(task).State = EntityState.Modified; 
    context.SaveChanges();

作为旁注,您可以在致电RedirectToAction时传递参数。 (仅当您要将已编辑任务的ID传递给Index操作时才执行此操作):

return RedirectToAction("Index", new { taskId = existingTask.Id });
//                                     ^^^^^^
//                                     must match parameter name of Index action