如何从ViewModel列表中发布ViewModel
本文关键字:ViewModel 列表 | 更新日期: 2023-09-27 18:16:25
我当前有一个视图,我将一个ViewModels列表传递给它。然后我想选择其中一个ViewModel并将其发布回我的控制器。我现在有一个foreach循环,遍历每个ViewModel并显示它们的数据。对于每个ViewModel,也有一个提交按钮,但它似乎没有像我希望的那样工作。
解释的代码(视图(:
@model IEnumerable<RoboticsScheduler.Models.UserVM>
...
@using (Html.BeginForm("UserApproved", "Approve"))
{
...
@foreach (var item in Model)
{
...
@*Modified model data*@
...
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Approve User" class="btn btn-default" />
</div>
</div>
}
}
然后,在我的接受控制器中,我将UserVM作为参数,但我在控制器中不断获得空的UserVM。
控制器中的代码:
public async Tas<ActionResult> UserApproved(UserVM uvm)
{
...
}
如果有人对我如何完成这样的事情提出建议,那就太好了!
编辑
显示更多的视图深度,并将BeginForm移动到循环中:
...
@foreach (var item in Model)
{
using (Html.BeginForm("Index", "Approved", FormMethod.Post))
{
<tr>
<td>
@Html.HiddenFor(modelItem => item.Id)
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@item.EmailConfirmed.ToString()
</td>
<td>
<span class="col-md-10">
@{List<string> roles = ViewBag.Roles;
int i = 0;
}
@foreach (string role in roles)
{
@Html.EditorFor(modelItem => item.Roles[i])
@Html.Label(role, new { @class = "control-label" })
<br />
}
</span>
</td>
<td>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Approve User" class="btn btn-default" />
</div>
</div>
</td>
</tr>
}
}
解决方案是了解MVC如何在发布表单时将值绑定回控制器。详细解释。。
解决方案:您的视图模型是@model IEnumerable<RoboticsScheduler.Models.UserVM>
,因此表单提交变得很棘手,因为您处理的是Not单个对象。你的for循环是正确的,但你需要了解它发生了什么。
@foreach (string role in roles)
{
@Html.EditorFor(modelItem => item.Roles[i])
@Html.Label(role, new { @class = "control-label" })
<br />
}
这里的编辑器渲染了一个名称类似item.Role
的HTML标记,这就是这里的问题。name参数是表单发布成功所需的唯一正确参数。所以你所要做的就是…
@Html.EditorFor(modelItem => item.Roles[i], new {Name = 'RoleType'})
在这里,我隐式地为输入标记指定一个名称。此外,我假设您的ViewModel UserVM具有一个名为RoleType的属性。低于
public class UserVM
{
public string RoleType {get;set;}
public int UserId {get;set;} // you will see why this in my below explanation
}
现在,当你提交表单时,MVC会看到控制器操作的输入参数类型,它的UserVM对象,现在它在这个对象内部查找一个与表单中的输入元素同名的属性。
建议:在阅读了您的评论后,我明白您希望显示一个角色下拉列表,用户可以从中选择一个角色。所以你可以试试这个。。
更改从Viewbag 提取数据的方式的逻辑
@{
List<string> roles = ViewBag.Roles;
int i = 0;
var RolesList = roles.select(c => new SelectListItem {Text=c,Value=c}).ToList();
}
上面的代码将使用Linq语法构建SelectListItem对象的列表(这是我们在MVC中处理下拉列表时必须使用的对象(。现在在里面您的表格更改为这个
@foreach (var item in Model)
{
using (Html.BeginForm("Index", "Approved", FormMethod.Post))
{
@Html.HiddenFor(modelItem => item.Id, new {Name = "UserId"})
@Html.DropDownList("RoleType",RolesList)
@Html.Label(role, new { @class = "control-label" })
<br />
}
}
因此,上面的语法显示它是一个下拉列表,并且有一个名称RoleType,还有一个隐藏字段,名称更改为UserId(正如我们在上面的解释中所知道的原因(。现在将在提交表单时发布。如果您希望其他字段也被发布,您可以将它们放在hiddenfor语法中。
注意:玩MVC时应该知道的主要一点是,默认的MVC模型绑定完全依赖于输入标签(也包括选择标签(的名称属性来实现成功发布。
附加信息:以上表单帖子等于在查询字符串中执行与此相同的操作。。
yourlocalhost/Approved/Index?RoleType="Admin"&UserId="23"
您仍然可以使用相同的控制器语法。这是为了让您更清楚MVC所做的模型绑定。您可以尝试并在action方法中检查对象,以查看填充到对象各自属性的值。
//Person
@model MvcApplication1.Models.Person
@{
ViewBag.Title = "Index";
}
<h2>Person</h2>
@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<div>
@Html.TextBoxFor(model => model.Id, new { id = "Id"})
</div>
<div>
@Html.TextBoxFor(model => model.Nome, new { id = "Name" })
</div>
if (Model != null && Model.Phone != null)
{
foreach (var phone in Model.Phone)
{
Html.RenderPartial("_Phone", phone);
}
}
<input type="submit" value="Save" />
}
//phone
@model MvcApplication1.Models.Phone
@using (Html.BeginCollectionItem("Phone"))
{
<div>
<div>
@Html.EditorFor(model => model.PhoneNumber)
</div>
</div>
}
使用Html.BeginCollectionItemhttps://www.nuget.org/packages/BeginCollectionItem/