为什么Html Helper为视图模型的子项添加前缀?

时间:2013-01-04 12:39:02

标签: razor

我有一个包含单个子实体和各种其他属性的视图模型。

在我看来,我想显示子实体的表单。 使用以下代码:

@Html.HiddenFor(model => model.Item.ItemID)

产生以下输出:

<input id="Item_ItemID" name="Item.ItemID" type="hidden" value="234" />

正如您所看到的,Html助手已经为idname属性添加了前缀,而我希望输出为

<input id="ItemID" name="ItemID" type="hidden" value="234" />

因此,前一个输出在提交表单时会导致错误,因为表单元素与子实体上的属性不对应。

我知道我可以通过对隐藏字段进行硬编码来解决这个问题

<input id="ItemID" name="ItemID" type="hidden" value="@Model.Item.ItemID" />

哪种方式打败了拥有Html助手的原因, 或者创建局部视图并传入子对象

@{Html.RenderPartial("ItemForm", Model.Item);}

我知道能够将html属性传递给方法,并且还编写自己的扩展方法,但是当涉及数据验证和jQuery时,事情变得更加复杂,即以下代码:

@Html.EditorFor(model => model.Item.Title)
@Html.ValidationMessageFor(model => model.Item.Title)

生成此代码:

<input class="text-box single-line" data-val="true" data-val-required="The Title field is required." id="Item_Title" name="Item.Title" type="text" value="Some text" />
<span class="field-validation-valid" data-valmsg-for="Item.Title" data-valmsg-replace="true"></span>

因此需要一种优雅的方法来保持属性名称的同步。

所以任何人都可以回答为什么HtmlHelper为视图模型的子项添加前缀? 作为一个后续问题,还有其他任何防止添加前缀的巧妙方法吗?

1 个答案:

答案 0 :(得分:6)

HTML助手是在考虑模型绑定约定的情况下构建的。例如,我想你有以下模型:

public class MyViewModel
{
    public ItemViewModel Item { get; set; }

    // ... other properties
}

public class ItemViewModel
{
    public int ItemID { get; set; }
}

并且相应的视图强烈输入MyViewModel

所以当你使用:

@Html.HiddenFor(model => model.Item.ItemID)

帮助程序生成:

<input id="Item_ItemID" name="Item.ItemID" type="hidden" value="234" />

因为当表单被POST回服务器时,这将允许您在相应的控制器操作中正确绑定视图模型:

[HttpPost]
public ActionResult Process(MyViewModel model)
{
    // model.Item.ItemID will be correctly bound here from the hidden field value
}

我猜您的问题来自于您的控制器操作将ItemViewModel作为参数而不是MyViewModel

[HttpPost]
public ActionResult Process(ItemViewModel model)
{
    // model.ItemID will not be correctly bound here from the hidden field value
}

因此,您可以使用[Bind]属性并指定一个前缀来帮助模型绑定器:

[HttpPost]
public ActionResult Process([Bind(Prefix="Item")] ItemViewModel model)
{
    // model.ItemID will be correctly bound here from the hidden field value
}

或简单地设计另一个视图模型,从中剥离所有不必要的属性,只留下Item属性。现在,您的控制器操作可以采用这种专门设计的视图模型。

正如您在一天结束时所看到的那样,如果正确设计视图模型,则可以完美地控制模型绑定。这都是关于ASP.NET MVC中的视图模型。他们解决了所有问题。