0

我正在我们公司的第一个 MVC3 项目上工作,但我遇到了障碍。似乎没有人能弄清楚发生了什么事。

我在页面上使用了一个复杂的模型:

public class SpaceModels : List<SpaceModel> {
    public bool HideValidation { get; set; }
    [Required(ErrorMessage=Utilities.EffectiveDate + Utilities.NotBlank)]
    public DateTime EffectiveDate { get; set; }

    public bool DisplayEffectiveDate { get; set; }
}

在控制器中,我创建了一个带有空白 SpaceModels 的 SpaceModels 对象,用于合并 Spaces 时(这将是目标 Space)。

// Need a list of the models for the View.
SpaceModels models = new SpaceModels();
models.EffectiveDate = DateTime.Now.Date;
models.DisplayEffectiveDate = true;
models.Add(new SpaceModel { StoreID = storeID, SiteID = siteID, IsActive = true });

        return View("CombineSpaces", models);

然后在视图中,我使用该 SpaceModels 对象作为模型,并以为生效日期制作文本框的形式:

@model Data.SpaceModels

@using (Html.BeginForm("CombineSpaces", "Space")) {
    <div class="EditLine">
        <span class="EditLabel LongText">
            New Space Open Date
        </span>
        @Html.TextBoxFor(m => m.EffectiveDate, new {
                        size = "20",
                        @class = "datecontrol",
                        // Make this as a nullable DateTime for Display purposes so we don't start the Calendar at 1/1/0000.
                        @Value = Utilities.ToStringOrDefault(Model.EffectiveDate == DateTime.MinValue ? null : (DateTime?)Model.EffectiveDate, "MM/dd/yyyy", string.Empty)
        })
        @Html.ValidationMessageFor(m => m.EffectiveDate)
    </div>

    <hr />        

    Html.RenderPartial("_SpaceEntry", Model);
}

被渲染的局部视图遍历所有 SpaceModel,并创建一个包含各个 SpaceModel 对象的 Edit 字段。(当空间被细分时,我使用列表来使用相同的视图。)

然后在 HttpPost 上,EffectiveDate 仍然回到它的 DateTime.MinValue 默认值:

[HttpPost]
public ActionResult CombineSpaces(SpaceModels model, long siteID, long storeID, DateTime? effectiveDate) {
// processing code
}

我添加了那个日期时间?effectiveDate 参数来证明更改时的值确实会返回。我什至尝试将 TextBox 的渲染移到 _SpaceEntry 部分视图中,但那里也没有任何效果。

我也尝试使用@Html.EditorFor(m => m.EffectiveDate)代替@Html.TextBoxFor(),但仍然返回 DateTime.MinValue。(顺便说一句,我的老板不喜欢放弃对渲染的控制@Html.EditorForModel。)

必须有一些我想念的简单的东西。如果您需要其他任何东西,请告诉我。

4

2 回答 2

1

查看源代码DefaultModelBinder特别是BindComplexModel(),如果它检测到集合类型,它将绑定单个元素,但不会尝试绑定列表对象本身的属性。

于 2012-08-28T23:20:53.900 回答
1

模型绑定所做的是尝试将视图中的事物或元素的名称与模型中的属性或操作方法中的参数相匹配。您不必传递所有这些参数,您所要做的就是将它们添加到您的视图模型中,然后调用TryUpdateModel您的操作方法。我不确定您要使用 SpaceModel 或 List 做什么,但我认为不需要从 List 继承。我相信你有充分的理由这样做。这是我将如何做到的。

视图模型

public class SpacesViewModel
{
    public DateTime? EffectiveDate { get; set; }
    public bool DisplayEffectiveDate { get; set; }
    public List<SpaceModel> SpaceModels { get; set; }
}

GET 操作方法

[ActionName("_SpaceEntry")]
public PartialViewResult SpaceEntry()
{
    var spaceModels = new List<SpaceModel>();
    spaceModels.Add(
        new SpaceModel { StoreID = storeID, SiteID = siteID, IsActive = true });

    var spacesVm = new SpacesViewModel
    {
        EffectiveDate = DateTime.Now,
        DisplayEffectiveDate = true,
        SpaceModels = spaceModels
    };

    return PartialView("_SpaceEntry", spacesVm);
}

POST 动作方法

[HttpPost]
public ActionResult CombineSpaces() 
{
    var spacesVm = new SpacesViewModel();

    // this forces model binding and calls ModelState.IsValid 
    // and returns true if the model is Valid
    if (TryUpdateModel(spacesVm))
    {
        // process your data here
    }
    return RedirectToAction("Index", "Home");
}

和视图

<label>Effective date: </label>
@Html.TextBox("EffectiveDate", Model.EffectiveDate.HasValue ?
    Model.EffectiveDate.Value.ToString("MM/dd/yyyy") : string.empty, 
    new { @class = "datecontrol" })

有时您需要使用隐藏字段显式绑定表单数据,例如

@Html.HiddenField("EffectiveDate", Model.EfectiveDate.)

为了绑定 SpaceModel 对象的属性,您可以将 SiteID 等单个属性添加到视图模型或为单个 SpaceModel 添加 SpaceModel 属性。如果要成功绑定复杂模型,请将其添加为Dictionary填充键值对而不是列表。然后,您应该将字典添加到视图模型。您甚至可以为分层数据添加字典字典。

我希望这有帮助 :)

于 2012-08-29T16:53:25.250 回答