【问题标题】:Using Editor Templates to Display Multiple Forms使用编辑器模板显示多个表单
【发布时间】:2012-03-12 11:03:00
【问题描述】:

我的问题与this one 非常相似。我正在开发的应用程序是用 MVC 3 和 Razor 编写的。它允许其用户从商店中选择商品并将每件商品发送到不同的地址。

这是我的 ViewModel:

public class DeliveryDetailsViewModel
{
    public FromDetailsViewModel From { get; set; }
    public IList<ToDetailsViewModel> To { get; set; }
}

public class DetailsViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

public class FromDetailsViewModel : DetailsViewModel
{
    public string StreetAddress { get; set; }
    public string Suburb { get; set; }
    public string Postcode { get; set; }
}

public class ToDetailsViewModel : DetailsViewModel
{
    public string Message { get; set; }
}

我的视图与下面类似。

@model Store.ViewModels.DeliveryDetailsViewModel

@Html.EditorFor(m => m.From)

@Html.EditorFor(m => m.To)

我的意图是显示一组表单(购物车中的每个项目一个),以使用户能够输入不同的交付详细信息。每个表单都有自己的提交按钮。

呈现“To”表单的编辑器模板如下:

@model Store.ViewModels.ToDetailsViewModel

@using (Html.BeginForm("ConfirmTo", "Delivery"))
{
    @Html.TextBoxFor(m => m.FirstName)
    @Html.TextBoxFor(m => m.LastName)
    @Html.TextBoxFor(m => m.Email)
    @Html.TextBoxFor(m => m.Message)

    <input type="submit" value="Confirm" />
}

我的控制器:

public class DeliveryController : Controller
{
    public ActionResult Index()
    {
        var model = new DeliveryDetailsViewModel();
        model.From = new FromDetailsViewModel();
        model.To = new List<ToDetailsViewModel>();
        return View(model);
    }

    public ActionResult ConfirmTo(ToDetailsViewModel toDetails)
    {
        // Save to database.
    }
}

我有几个问题:

  1. “to”编辑器模板不呈现任何内容(尽管它曾经如此)。它指出模型类型不匹配(即ToDetailsViewModelList&lt;ToDetailsViewModel&gt; 不同),尽管我认为编辑器模板应该将索引附加到输入字段名称以启用正确的绑定。

  2. 当单击确认并提交 To 列表中的第一个表单时,控制器会收到具有正确绑定的视图模型。提交以下任何表单(索引为 1 或更大)会调用 ConfirmTo 操作并传递一个为空的 ToDetailsViewModel

我们将不胜感激,如果您想了解有关我遇到的问题或我正在使用的代码的更多信息,请随时询问。

【问题讨论】:

    标签: c# asp.net-mvc-3 forms binding viewmodel


    【解决方案1】:

    1) “to”编辑器模板不呈现任何内容

    在您的控制器操作中,您没有在列表中添加任何内容。你只是实例化了它。所以放一些元素:

    model.To = new List<ToDetailsViewModel>();
    model.To.Add(new ToDetailsViewModel());
    model.To.Add(new ToDetailsViewModel());
    ...
    

    2) 当点击 Confirm 并提交 To 列表中的第一个表单时,控制器接收到具有正确绑定的视图模型。提交以下任何表单(索引为 1 或更大)都会调用 ConfirmTo 操作并传递一个为 null 的 ToDetailsViewModel。

    如果这对第一个元素也有效,我会感到惊讶,因为输入字段当前没有正确的名称。它们都以 To[someIndex] 为前缀,而您的 ConfirmTo 需要平面模型,而不是集合。

    因此,您可以将前缀设置为空字符串,以便在 ~/Views/Shared/EditorTemplates/ToDetailsViewModel.cshtml 编辑器模板中生成正确的输入元素:

    @model ToDetailsViewModel
    @{
        ViewData.TemplateInfo.HtmlFieldPrefix = "";
    }
    @using (Html.BeginForm("ConfirmTo", "Home"))
    {
        @Html.TextBoxFor(m => m.FirstName)
        @Html.TextBoxFor(m => m.LastName)
        @Html.TextBoxFor(m => m.Email)
        @Html.TextBoxFor(m => m.Message)
    
        <input type="submit" value="Confirm" />
    }
    

    【讨论】:

    • 感谢您的帮助 Darin,我的问题的第 1 部分已解决!关于输入字段前缀,您提供的解决方案有效,但这意味着如果我返回视图并为其提供更新的模型,所有 FirstName 字段都会获得我输入的值,而不仅仅是我输入的一个表单已编辑。 (我希望我能很好地表达自己,以便被理解。)
    • 我通过使用 RedirectToAction("Index") 而不是返回 View("Index", model) 解决了这个问题。谢谢达林!
    【解决方案2】:

    1) 你有没有试过这个,因为你的视图模型有

    public IList<ToDetailsViewModel> To { get; set; }
    

    To 是一个列表,因此您的编辑器模板应该有

    @model IEnumerable<Store.ViewModels.ToDetailsViewModel>
    

    模板应该使用foreach

    @foreach(model in Model){}
    

    【讨论】:

    • 不幸的是我试过了,是的。因为“to”表单在页面上出现多次,模型绑定器会感到困惑,并使用提交的输入填写所有“FirstName”字段。这是因为每个表单的输入名称都是相同的。
    • 此外,将视图模型列表传递给 EditorFor() 助手应该处理创建具有不同名称的字段。例如:“To_0__FirstName”和“To_1__FirstName”。
    • 那不如使用提交按钮,直接使用,写一个jQuery来获取信息并通过jQuery提交
    • 为此,您可以将 To 的 id 绑定到必要的列
    • 我想到了,这是一个非常好的建议,但是如果用户禁用了 JavaScript 怎么办?
    猜你喜欢
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    相关资源
    最近更新 更多