Asp.net mvc 3 在同一父视图上多次使用一个局部视图
我正在使用MVC3剃须刀。我有一个场景,我必须在同一父视图上多次使用局部视图。我遇到的问题是,当父视图被渲染时,它会在这些局部视图中生成输入控件的相同名称和ID。由于我的局部视图绑定到不同的模型,因此当视图返回“保存”时,它会崩溃。知道如何使控件id/名称唯一吗?可能知道如何给它们加前缀 等待Asp.net mvc 3 在同一父视图上多次使用一个局部视图,asp.net-mvc-3,model-binding,Asp.net Mvc 3,Model Binding,我正在使用MVC3剃须刀。我有一个场景,我必须在同一父视图上多次使用局部视图。我遇到的问题是,当父视图被渲染时,它会在这些局部视图中生成输入控件的相同名称和ID。由于我的局部视图绑定到不同的模型,因此当视图返回“保存”时,它会崩溃。知道如何使控件id/名称唯一吗?可能知道如何给它们加前缀 等待 Nabeel就个人而言,我更喜欢使用编辑器模板,因为它们会处理这个问题。例如,可以使用以下视图模型: public class MyViewModel { public ChildViewMode
Nabeel就个人而言,我更喜欢使用编辑器模板,因为它们会处理这个问题。例如,可以使用以下视图模型:
public class MyViewModel
{
public ChildViewModel Child1 { get; set; }
public ChildViewModel Child2 { get; set; }
}
public class ChildViewModel
{
public string Foo { get; set; }
}
以及以下控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Child1 = new ChildViewModel(),
Child2 = new ChildViewModel(),
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
在Index.cshtml
视图中:
@model MyViewModel
@using (Html.BeginForm())
{
<h3>Child1</h3>
@Html.EditorFor(x => x.Child1)
<h3>Child2</h3>
@Html.EditorFor(x => x.Child2)
<input type="submit" value="OK" />
}
使用编辑器for可以为主视图模型的不同属性包含模板,并将生成正确的名称/ID。除此之外,您还可以在后期操作中正确填充视图模型。还有一种替代方法:
ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "prefix";
对于2,您可以使用UpdateModel
恢复数据,如下所示:
UpdateModel(producto, "prefix");
这不是很明智,因为您的操作不会将数据作为参数接收,而是在稍后更新模型。这有几个不便之处:1)通过查看其签名不清楚您的操作需要什么2)为操作提供输入以进行单元测试并不容易3)操作易受溢出参数的影响(用户提供的参数不应该存在,并且映射到模型)
但是,对于2,有一种替代方法:注册一个自定义模型绑定器,允许您删除前缀。自定义模型绑定器必须知道这一点
一个很好的解决方案是这样的,所以Q&A:但它有一个小缺陷:如果在局部视图中添加一个名为“\uu prefix”的隐藏字段,并多次将其作为局部视图呈现,则该ID将在页面中的多个不同元素中重复,这是不允许的,并且可能会引发一些问题。提供前缀的最重要原因之一是,对于一个实体的多个实例,呈现与局部视图相同的“编辑”视图。也就是说,这会发生在像gmail这样的页面上,你可以一次编辑多封电子邮件
这个问题有几种可能的解决方案
其中之一是将前缀作为查询字符串或routedata值提供,而不是作为表单字段提供,这样可以避免Id冲突,并且可以由模型绑定器找到。(它可以始终具有相同的名称)
另一种解决方案是使用具有固定图案的隐藏字段,但对于每个渲染视图都不同。前缀可以遵循此模式以实现唯一性:“PP$ActionControllerId”类似于“PP$EditProduct23”,它对于每个渲染视图都是唯一的,并且可以很容易地在请求参数之间找到,以查找以“PP$”开头的参数
最终的解决方案是只在视图中创建前缀,而不在任何类型的请求参数中提供前缀。模型绑定器必须通过检查请求参数的名称来查找前缀,直到找到前缀符合模式的前缀
当然,自定义ModelBinder必须适应所选约定
UpdateModel(producto, "prefix");