MVC 4 Razor,使用部分视图发布表单

15

我刚接触MVC 4和Razor。我有一个包含多个局部视图的视图。由于局部视图的功能,我计划在其他视图中重复使用它们。

我的模型是一组复杂对象,例如:

    public class EmployeeInfo
    {
        public EmployeeContactInfo contactInfo { get; set; }
        public List<TelephoneInfo> phoneDetails { get; set; }
        public AddressDetails addressDetails { get; set; }
    }
我的主视图模型是EmployeeInfo,其他局部视图的模型分别为TelephoneInfoEmployeeContactInfoAddressDetails
我尝试使用RenderPartialRenderActionPartial来加载我的局部视图,例如:
    @using (Html.BeginForm())
    {
    @Html.Partial("ContactInfo",Model.contactInfo)
    }
当主表单提交时,主模型不具有部分视图的更新值。
我搜索了这个问题,并发现了以下两个解决方案:
1. 使用 `EditorFor` - 这个方法可行,模型会得到更新,但是我有一个不仅包含文本框而且还包含其他控件的集合,这些控件还具有一些内部操作(比如搜索地址),我还需要在其他地方重用同样的部分视图(比如在经典 ASP.NET 中的用户控件)。
2. 使用 `RenderAction` 而不是 `RenderPartial` - 对我来说它没有起作用。
如果我理解有误或者做错了什么,请告诉我。

这可能会有所帮助:https://dev59.com/Dmsz5IYBdhLWcg3wv6nu - Jason Evans
3个回答

27

另一个选择是创建一个编辑模板。例如,在你的主视图中:

@using (Html.BeginForm())
{
    @(Html.EditorFor(m => m.ContactInfo))
}

现在,在您的 Views/Shared 文件夹中(或者 Views/ControllerName 文件夹,例如 Views/Home),创建一个名为“EditorTemplates”的新文件夹。在该文件夹中创建一个名为 EmployeeContactInfo.cshtml 的 cshtml 视图文件(提示:cshtml 的名称应为数据类型名称,例如 stringbool 或在此情况下是您的客户联系信息类型)。在该视图文件中,添加以下内容:

@model EmployeeContactInfo

@Html.LabelFor(m => m.Email)
@Html.TextBoxFor(m => m.Email)

当您将数据发送回控制器时,这些值将作为返回的模型的一部分包含在其中。


@indranilpal - 编辑器模板类似于部分视图,但它们被设计为按照您想要使用的方式(作为可重用组件)使用。它允许您根据类型呈现组件,并具有适当的命名约定以支持复杂的嵌套对象。它还支持对象集合,并将呈现集合。 - Erik Funkenbusch
@MystereMan - 没错,我想要一个可以重复使用的东西,我认为编辑器模板会救我于水深火热之中。感谢JasonEvans和你,MysteryMan :) - indranil pal
请注意行末的分号。实际上,它并不是必需的,因为它会将字符打印到 HTML 中。谢谢! - Diego
@Diego 干杯。已经移除了 ; 字符。 - Jason Evans
1
哇!我刚刚在.NET Core和新的标签助手中使用了它。我以为它不会起作用,但它像魔法一样奏效了。谢谢! - Pinski
@Pinski 很高兴这些信息对你有帮助 :) - Jason Evans

8
问题在于您的主表单期望具有名称为contactInfo.property的元素,可能在您的局部文件中生成的名称没有正确的标识符,这个问题会导致MVC的默认模型绑定器出现问题。您可以创建一个自定义模型绑定器,但需要付出艰苦努力,或者您有两种方法可以用较少的工作来解决问题。
1. 强制生成元素名称
例如,如果您的EmployeeContactInfo类包含一个字符串地址属性,则必须使用此助手:
@Html.TextBox("contactInfo.Address", model.Address)

导致以下结果:
<input type="text" name="contactInfo.Address" id="contactInfo_Address" />

改为:

@Html.TextBoxFor(m=> m.Address)

导致以下结果:
<input type="text" name="Address" id="Address" />

2. 传递整个模型:

如果您传递整个模型,则生成的名称将是正确的,因此您可以使用助手:

@Html.TextBoxFor(m=> m.contactInfo.Address)

导致以下结果:
<input type="text" name="contactInfo.Address" id="contactInfo_Address" />

整个模型的传递是可行的,我同意,但为了在其他地方重复使用视图,我不希望其他视图每次都创建一个新模型并从其实际模型进行映射。我也考虑过控件中的“名称”,但如果将其放在htmlAttributes列表中进行呈现时,当控件呈现时,名称会改回属性名称,因此这种方法不起作用。 - indranil pal

-2

Partial View页面类似于用户控件

  1. _login.cshtml是一个部分视图
  2. 如果您使用了部分视图,则名称后面加下划线:

    <div style = "margin:3%;"> @Html.Partial("~/Views/Shared/_login.cshtml",Model.login)
    </div>

  3. Model.login是一个对象。因此,在此对象中,您可以为任何页面分配值。

  4. 根据对象的值,部分视图将显示。


我相信你正在使用一个项目的示例代码,但是这段代码本身并不能帮助用户解决这个具体的问题。 - reZach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接