【问题标题】:Losing data in models and collections inside the ViewModel on postback在回发时丢失 ViewModel 内的模型和集合中的数据
【发布时间】:2012-01-05 06:24:30
【问题描述】:

我正在使用一个视图模型,其中每个局部视图都包含一些其他模型(实体)。 我通过传递 ViewModel 内部的实体来呈现部分视图。我的局部视图有一些字段和一些按钮。单击按钮(在我的部分视图内)时,表单将与子实体中的数据一起发回,而我的视图模型总是以空值形式发回... 我需要数据在回发时出现在我的视图模型中。

所有视图都是强类型的:

代码:

public class OrdersVM
{
    public FiltersVM filterCriteria { get; set; }
    public IEnumerable<MeterInventory> meters { get; set; }
    public string assignTo { get; set; }
    public IEnumerable<SelectListItem> AssigneeOptions { get; set; }
}

public partial class Meters
{
    public int MTRNO { get; set; }
    public string LOCName { get; set; }
}

public class FiltersVM
{
    public string Center { get; set; }
    public DateTime? DueDate { get; set; }
}

查看代码

@model OrdersVM
@{
    ViewBag.Title = "Orders";
}
@using (Html.BeginForm())
{   
    <div>
        @Html.Partial("~/Views/Base/Filters.cshtml", Model.filterCriteria)
    </div>
    @foreach (var item in Model.meters)
    {  
    <table>
        <tr>
            <td>
                @Html.Encode(item.LOCNAME)
            </td>
        </tr>
    </table>
    }
}

控制器代码

[HttpPost]
public ActionResult Index(OrdersVM orders, FiltersVM filters)
{
    //orders is null
    //filters has values
}

感谢 Olivehour。我正在使用部分视图“Filters.cshtml”。并且渲染相同。

下面是部分视图的代码:

@model ViewModels.FiltersVM  <fieldset>
    <legend>Order Assignment</legend>
    <table id="tbl1" class="tableforcontrols">
        <tr>
            <td>
                <div class="editor-label">
                    @Html.LabelFor(model => model.LDC)
                </div>
            </td>
            <td>
                <div class="editor-field">
                    <input type="submit" value="Search" id="btnSearch" name="button" />
                </div>
            </td>
            <td>
                <div class="editor-field">
                    <input type="submit" class="cancel" value="Reset" id="btnReset" name="button" />
                </div>
            </td>
        </tr>
    </table>    </fieldset>     

我尝试使用单个参数“OrdersVM”(父视图模型),但没有运气。

[HttpPost]
public ActionResult Index(OrdersVM orders)

但如果我将父视图模型传递给部分视图,它会将数据保存在 OrdersVM.filterCriteria 中,但不用于属性(IEnumerable 仪表、字符串 assignTo 和 Enumerable AssigneeOptions)

@Html.Partial("~/Views/Base/Filters.cshtml", Model)

我是 MVC 的新手。如果有人找到解决方案,请告诉我。

提前致谢。

【问题讨论】:

    标签: asp.net-mvc-3 postback viewmodel partial-views


    【解决方案1】:

    看起来您在这里遇到了一些问题。在您的操作方法中,orders arg 为 null 的一个可能原因是因为它看起来不像您正在呈现任何输入元素。你只有@Html.Encode(item.LOCNAME)

    为了让默认模型绑定器构造OrdersVM 的实例并将其传递给操作方法,它需要有来自HTTP POST 的输入。你需要更像@Html.TextBoxFor(m =&gt; item.LOCNAME)

    我认为第二个问题是 action 方法中有 2 个参数。因为OrdersVM 已经有一个FiltersVM 属性,所以你应该可以在action 方法中有一个OrdersVM 参数。在 HTTP POST 期间,您可以从 OrdersVM.filterCriteria 访问 FiltersVM 属性。不过,这将导致您的第三个挑战,因为 OrdersVM 上的 meters 属性是 IEnumerable 集合。

    为了解决这个问题,首先阅读this article about model binding collections。它很旧,但它仍然适用于 MVC3。阅读并真正了解它。

    如果您不喜欢使用整数来索引您的集合字段,有一个HTML helper written by Steve Sanderson 允许您使用 GUID 索引集合输入。我们一直都在使用它,但它可能很棘手——主要是,您应该始终将集合项放在局部视图中。目前,您最好使用 Haacked 文章中概述的基于整数的索引。

    【讨论】:

    • 感谢 Olivehour。我会尝试浏览链接...我已经更新了我的问题,请看一下。
    【解决方案2】:

    听起来您来自 Webforms。要过渡到 MVC,您需要消除 PostBack 的想法。这是网络上并不真正存在的概念,但 Webforms 为我们伪造了它。

    在 MVC 中,您通常从 /edit/{someId} 之类的 GET 请求开始。从这里您从数据库加载视图模型的数据并渲染视图。现在假设视图模型中的所有数据都是可编辑的,因此每个属性都有自己的输入字段。用户编辑一些数据并保存表单。这会向服务器发出 POST。

    假设我们有这个 POST 方法

    [HttpPost]
    public ActionResult Edit(MyViewModel model)
    

    在这种情况下,您拥有模型绑定所需的所有数据,因为所有数据都存在于表单中。

    您可以这样做并渲染相同的视图,因为所有数据都是数据绑定的。

    [HttpPost]
    public ActionResult Edit(MyViewModel model){
       return View(model);
    }
    

    现在让我们假设您的表单中有一个下拉菜单。然后你的视图模型中就会有这两个属性。

    public int CarId { get; set; }
    public IEnumerable<SelectListItem> CarOptions {get; set; }
    

    当您这次发布表单时,CarId 将填充到 ViewModel 中,而不是 CarOptions 中,因为它们不是表单数据的一部分。如果您想再次返回相同的视图,您要做的就是重新加载丢失的部分。

    [HttpPost]
    public ActionResult Edit(MyViewModel model){
       model.CarOptions = LoadCarOptions();
       return View(model);
    }
    

    如果你把它放在一个隐藏的字段中,当然也可以对它进行模型绑定。但是再次从服务器/数据库重新加载它更容易并且可能更有效。这是使用 MVC 时采用的常规方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多