在回发时丢失ViewModel内的模型和集合中的数据

时间:2012-01-05 06:24:30

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

我正在使用一个viewmodel,它包含每个局部视图的一些其他模型(实体)。 我通过传递ViewModel中的实体来渲染局部视图。我的局部视图有几个字段和一些按钮。单击按钮(在我的局部视图中),表单将被回发,数据在子实体中,而我的viewmodel总是以null返回... 我需要在回发后的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的新手。如果有人找到解决方案,请告诉我。

提前致谢。

2 个答案:

答案 0 :(得分:0)

看起来你在这里有几个问题。在您的操作方法中,订单arg为null的一个可能原因是因为它看起来不像是在渲染任何输入元素。你只有@Html.Encode(item.LOCNAME)

为了使默认模型绑定器构造OrdersVM的实例并将其传递给action方法,它需要从HTTP POST输入。您需要更像@Html.TextBoxFor(m => item.LOCNAME)的内容。

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

要解决这个问题,首先要读几this article about model binding collections次。它已经过时了,但它仍适用于MVC3。阅读它,并真正包围它。

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

答案 1 :(得分:0)

听起来你是来自Webforms。要转换到MVC,您需要删除PostBack的想法。这个概念在网络上并不存在,但Webforms为我们伪造了它。

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

假设我们有这个POST方法

[HttpPost]
public ActionResult Edit(MyViewModel model)

在这种情况下,您需要模型化所需的所有数据,因为表格中存在所有数据。

您可以执行此操作并获取相同的视图,因为所有数据都是数据绑定的。

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

现在让我们假装你的表格中有一个下拉列表。然后,您将在viewmodel中拥有这两个属性。

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时采用的常规方法。

相关问题