我正在尝试发布包含列表<> 项目的模型,如下所示:
public class AddSubscriptionPlanModel
{
public AddSubscriptionPlanModel()
{
AllFeatures = new List<Feature>();
}
public int Id { get; set; }
public int SubscriptionPlanId { get; set; }
public int SubscriptionId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
[Display(Name = "No Of Users")]
public int? NoOfUsers { get; set; }
[Display(Name = "Duration Type")]
public DurationType DurationType { get; set; }
public int Duration { get; set; }
public decimal Amount { get; set; }
public int SubscriptionPlanTrailId { get; set; }
public int FeatureId { get; set; }
public DateTime CreatedDateUtc { get; set; }
public DateTime LastUpdatedUtc { get; set; }
public int CreatedBy { get; set; }
public int LastUpdatedBy { get; set; }
public List<Feature> AllFeatures { get; set; }
}
我在get方法中填充所有必填字段并从数据库中提供List
public ActionResult Mapping(int id)
{
var features = FeatureManager.GetAllFeatures();
var model = new Ejyle.DevAccelerate.Web.App.Models.SubscriptionPlan.AddSubscriptionPlanModel();
model.AllFeatures = features;
model.Id = id;
model.SubscriptionId = id;
model.NoOfUsers = 20;
model.SubscriptionPlanId = 1;
model.SubscriptionPlanTrailId = 1;
model.Amount = 1000;
model.CreatedBy = 1;
model.LastUpdatedBy = 1;
model.FeatureId = 1;
model.Duration = 20;
return View(model);
}
我的观看代码如下所示:
@using (Html.BeginForm("Mapping", "SubscriptionPlans", FormMethod.Post))
{
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.Amount)
@Html.HiddenFor(model => model.Duration)
@Html.HiddenFor(model => model.FeatureId)
@Html.HiddenFor(model => model.CreatedBy)
@Html.HiddenFor(model => model.LastUpdatedBy)
@Html.HiddenFor(model => model.NoOfUsers)
@Html.HiddenFor(model => model.SubscriptionId)
@Html.HiddenFor(model => model.SubscriptionPlanId)
@Html.HiddenFor(model => model.SubscriptionPlanTrailId)
@Html.HiddenFor(model => model.AllFeatures)
<table class="table table-striped">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.IsActive)
</th>
</tr>
</thead>
<tbody>
@for (int i=0; i < Model.AllFeatures.Count; i++)
{
<tr>
@Html.HiddenFor(model => model.AllFeatures[i].Id)
@Html.HiddenFor(model => model.AllFeatures[i].Name)
@Html.HiddenFor(model => model.AllFeatures[i].IsActive)
<td>
@Html.TextBoxFor(model => model.AllFeatures[i].Id)
</td>
<td>
@Html.TextBoxFor(model => model.AllFeatures[i].Name)
</td>
<td>
@Html.EditorFor(model => model.AllFeatures[i].IsActive)
</td>
</tr>
}
</tbody>
</table>
<input type="submit" class="btn btn-success" value="Submit" name="Submit"/>
}
在“视图”上,列表项正确呈现,甚至我可以编辑这些字段 但是在帖子中,所有属性都具有除 AllFeatures 列表项属性之外的值,该属性始终显示count = 0。
编辑1:这是渲染功能时我的视图的样子
编辑2:
发布方法的签名:
[HttpPost]
public ActionResult Mapping(AddSubscriptionPlanModel model)
{
}
答案 0 :(得分:3)
但是在帖子上,所有属性都具有除AllFeatures列表项属性之外的值,该属性始终显示count = 0。
AllFeatures
是Feature
的通用列表。当你这样做时:
@Html.HiddenFor(model => model.AllFeatures)
Razor视图引擎将呈现:
<input id="AllFeatures"
name="AllFeatures"
type="hidden"
value="System.Collections.Generic.List`1[Namespace.Feature]">
<!--Where Namespace is the Namespace where Feature is defined. -->
换句话说,HiddenFor
会调用该项目的ToString()
,只需将其放入input
代码的value
属性中。
POST后会发生什么
当您发布表单时,DefaultModelBinder
正在查找名为AllFeatures
但属于string
的属性,以便将其分配给它:
System.Collections.Generic.List`1[Namespace.Feature]
由于您的模型没有类型AllFeatures
的{{1}},所以找不到它,因此它只是忽略它并绑定所有其他属性。
AllFeatures列出项属性,它始终显示count = 0。
是的,它会,这不是您发布的string
列表,而是来自构造函数的列表,它显然是一个带有计数0的空列表:
AllFeatures
我不确定您为什么要将所有功能发送到客户端(浏览器),然后您需要将其发回服务器。
<强>解决方案强>
要解决此问题,只需删除此行:
public AddSubscriptionPlanModel()
{
AllFeatures = new List<Feature>();
}
现在它不会在绑定期间造成任何混淆,MVC会将循环中的项绑定到@Html.HiddenFor(model => model.AllFeatures)
属性。
事实上,你真正需要的唯一代码,就我从你的问题中可以看出的那样(如果你因为其他原因需要隐藏字段,我可能会错。但如果你只是想让用户编辑AllFeatures,您不需要任何隐藏字段):
AllFeatures
答案 1 :(得分:1)
我认为您的问题可能是嵌套属性。您可能需要查看已发布的表单并查看其外观。
假设模型绑定适用于嵌套属性,您的标记看起来是正确的 - 我不确定它是什么。 (只是为了确保我搜索并找到了这个旧的Haack帖子,表明你做得对:Haack Post)
作为一种变通方法(和POC),您可以尝试以下操作:为您的功能添加一个新参数,将其发布为您现在正在执行但不是嵌套(因此您无法使用Model For HTML帮助程序)然后在控制器中,您可以将其设置回主对象的features属性。
答案 2 :(得分:1)
如何在视图中绑定到列表的上下文中这样做是不正确的。
查看:
@model Testy20161006.Controllers.AddSubscriptionPlanModel
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Mapping</title>
</head>
<body>
@*I am using controller home*@
@using (Html.BeginForm("Mapping", "Home", FormMethod.Post))
{
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.Amount)
@Html.HiddenFor(model => model.Duration)
@Html.HiddenFor(model => model.FeatureId)
@Html.HiddenFor(model => model.CreatedBy)
@Html.HiddenFor(model => model.LastUpdatedBy)
@Html.HiddenFor(model => model.NoOfUsers)
@Html.HiddenFor(model => model.SubscriptionId)
@Html.HiddenFor(model => model.SubscriptionPlanId)
@Html.HiddenFor(model => model.SubscriptionPlanTrailId)
@Html.HiddenFor(model => model.AllFeatures)
<table class="table table-striped">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.IsActive)
</th>
</tr>
</thead>
<tbody>
@for (int i = 0; i < Model.AllFeatures.Count; i++)
{
<tr>
@*BE SURE to get rid of these*@
@*@Html.HiddenFor(model => model.AllFeatures[i].Id)
@Html.HiddenFor(model => model.AllFeatures[i].Name)
@Html.HiddenFor(model => model.AllFeatures[i].IsActive)*@
<td>
@Html.TextBoxFor(model => model.AllFeatures[i].Id)
</td>
<td>
@Html.TextBoxFor(model => model.AllFeatures[i].Name)
</td>
<td>
@Html.EditorFor(model => model.AllFeatures[i].IsActive)
</td>
</tr>
}
</tbody>
</table>
<input type="submit" class="btn btn-success" value="Submit" name="Submit" />
}
</body>
</html>
控制器:
[HttpPost]
public ActionResult Mapping(AddSubscriptionPlanModel addSubscriptionModel, FormCollection formCollection)
{
var AllFeatures = String.Empty;
var index = "AllFeatures[";
foreach (var item in formCollection)
{
if (item.ToString().Contains(index))
{
AllFeatures += " " + formCollection.GetValues(item.ToString())[0];
}
}
//put breakpoint here to see userValues