将页面视图模型传递给表单

时间:2017-08-25 13:24:48

标签: asp.net-mvc forms

我有一个.net MVC页面,其中有一个用于从数据库编辑实体的表单。表单中有一些动态选择列表字段,需要从数据库中填充。

我传递一个包含实体数据的PageView模型,以及填充选择列表的实体列表,如下所示:

public class EditPortalPage
{
    public PortalViewModel Data { get; set; }
    public IEnumerable<SelectListItem> Cultures { get; set; }        
}

在我的视图中我有

  

@model Website.Models.Portals.EditPortalPage

位于页面顶部

我可以轻松填充表单:

    @Html.EditorFor(model => model.Data.Name, new { htmlAttributes = new { @class = "form-control" } })
    @Html.LabelFor(model => model.Data.Name)
    @Html.ValidationMessageFor(model => model.Data.Name, "", new { @class = "text-danger" })


    @Html.DropDownListFor(model => model.Data.DefaultCultureId, new SelectList(Model.Cultures, "Value", "Text"), new { @class = "mdb-select colorful-select dropdown-info" })
    @Html.LabelFor(model => model.Data.DefaultCultureId)
    @Html.ValidationMessageFor(model => model.Data.DefaultCultureId, "", new { @class = "text-danger" })

问题是这会为我的表单字段产生混乱的Id和Name属性。在上面的例子中,它产生:

Name Field ID: Data_Name 
Name Field Name: Data.Name

设置它的正确方法是什么,所以名称和ID不包含'数据'前缀

我可以直接将数据模型传递给表格吗?

2 个答案:

答案 0 :(得分:1)

HtmlHelper方法根据属性的名称生成nameid属性。在您的情况下,它是一个嵌套属性,因此它为Data.属性生成name前缀,在id属性的情况下,它替换.(点)使用_(下划线),以便可以在jquery选择器中使用id(否则点和后面的文本将被解释为类选择器。

基于属性名称的id属性可以确保一个唯一的id(因此有效的html),我不确定为什么你认为它'混乱',但你总是可以覆盖使用

的值
@Html.EditorFor(m => m.Data.Name, new { htmlAttributes = new { id = "xxx",  @class = "form-control" } })

如果要在css或javascript / jquery选择器中使用<input id="xxx" .... />(这是xxx属性的唯一目的),将呈现id

然而,name属性肯定不会“搞砸”,如果它被更改,则在提交时它不会绑定到您的模型。在任何情况下,您都不应该在使用name方法时尝试更改HtmlHelper属性。

我猜你(错误地)将你的数据模型用作POST方法中的参数,在这种情况下你可以使用Prefix属性的[Bind]属性(尽管是{{ 1}}属性永远不应该与视图模型一起使用)

[Bind]

删除public ActionResult Edit([Bind(Prefix = "Data")]PortalViewModel model) 前缀并绑定到"Data."

然而,这里真正的问题是你错误地使用了视图模型。查看模型(尤其是在编辑数据时)不应包含数据模型。它们仅包含视图中所需的数据模型的属性。视图模型的一些优点包括分离关注,防止不足和过度发布攻击,添加不适用于数据模型的显示属性的功能,以及添加其他视图特定属性的功能。在你的情况下,你已经否定了除了最后一点之外的所有事情。您应该查看模型

PortalViewModel

并在POST方法中,将视图模型映射到数据模型并保存数据模型。另请参阅What is ViewModel in MVC?

作为旁注,在public class EditPortalPage { public string Name { get; set; } [Display(Name = "Culture")] [Required(ErrorMessage = "Please select a culture")] public int? SelectedCulture { get; set; } //nullable and Required to protect against under-posting attacks ... // other properties of PortalViewModel that you need in the view public IEnumerable<SelectListItem> Cultures { get; set; } } 方法中使用new SelctList(..)是无意义的额外开销 - 它只是从第一个创建另一个相同的DropDownList(),而您的代码应该只是

IEnumerable<SelectListItem>

答案 1 :(得分:0)

如果我正确理解了Q,您可以使用部分"_data.cshtml"

@model PortalViewModel
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })

将数据传递给视图中的部分:

@Html.Partial("_data",model.Data)