2

尝试将模型绑定到我的视图模型时遇到一些问题。

因此,基本的视图模型是:

public class RegistrationVM
{
    public TravelHistoryVM TravelHistory {get;set;}
    public UserDetailVM UserDetails {get;set;}
    public ICollection<HandsetDevicesVM> ExistingDevices {get;set;}
}

3 个其他视图模型的包装器,每个视图模型都包含通常的字符串、整数和布尔值带。暂时忽略 HandsetDevicesVM 的集合。

我有以下视图(为清晰起见示例)

@using (Html.BeginForm())
{
    @Html.ValidationSummary(false)

    @Html.LabelFor(model => model.TravelHistory.DoNotTravel)
    @Html.CheckBoxFor(model => model.TravelHistory.DoNotTravel)

    @Html.EditorFor(model => model.UserDetails, "UserDetailsHidden")
}

'TravelHistory' 对象绑定良好,没有问题。回发数据时,“UserDetails”对象始终为空。

模板肯定是渲染的,我可以从 HTML 中看出。模板本身如下所示:

@model Foo.Bar.UserDetailVM
@Html.HiddenFor(model => model.EmailAddress)
@Html.HiddenFor(model => model.FirstName)
@Html.HiddenFor(model => model.Surname)
@* etc etc *@

生成的 HTML 是

<input data-val="true" data-val-required="The Email Address field is required." id="UserDetails_EmailAddress" name="UserDetails.EmailAddress" type="hidden" value="stack@overflow.com" />
<input data-val="true" data-val-required="The First Name field is required." id="UserDetails_FirstName" name="UserDetails.FirstName" type="hidden" value="Stack" />
<input data-val="true" data-val-required="The Surname field is required." id="UserDetails_Surname" name="UserDetails.Surname" type="hidden" value="Overflow" />

我在另一个没有问题的视图上使用此 EditorTemplate(它绑定到该视图模型没有问题)。

最后,使用 Fiddler 我可以确定正在发布的信息.. 我认为

UserDetails.EmailAddress=stack%40overflow.com.test&UserDetails.FirstName=stack&UserDetails.Surname=overflow

有任何想法吗?我应该将调试工作集中在哪里?

Edit1:刚刚从 ModelState 对象中注意到了这一点

AttemptedValue: 'Foo.Bar.UserDetailVM'

所以它似乎试图将字符串值 'Foo.Bar.UserDetailVM' 绑定到对象并且(显然)失败。

编辑2:

[HttpPost]
public ActionResult Travel(RegistrationVM model)

根据要求,我要发布的操作

编辑3:

啊。。好吧,回到一个阶段,这是提供视图的操作方法

[HttpGet]
public ActionResult Travel(PreRegistrationVM model)
{
    if (TempData["PreRegistrationVM"] != null)
    {
        model = (PreRegistrationVM)TempData["PreRegistrationVM"];
    }
    var newModel = new RegistrationVM(model);
    return View(newModel);
}

这就是我一直在使用的(因此是不起作用的过程的一部分)。本质上,来自先前步骤的信息保存在 TempData 中并在此方法中获取。然后它被用来实例化上面的虚拟机。此时(如果我在此处插入断点),模型将按照我的预期填充数据。

如果我将其修改为以下内容:

[HttpGet]
public ActionResult Travel(PreRegistrationVM model)
{
    var newModel = new RegistrationVM 
    {
        FirstName = "Stack",
        Surname = "Overflow"
    };
    return View(newModel);
}

它按预期绑定。TempData 是这里的罪魁祸首吗?

4

1 回答 1

0

快速背景检查:这是在创建“向导”逐步注册过程时遇到的问题。我想避免在注册完成之前将信息保存到数据库中。因此,这个想法是使用 TempData 集合来存储动作之间的信息,并使用 RedirectToAction 一步一步地移动。

对于它的价值,我修改了使用 TempData 这样的方法

[HttpGet]
public ActionResult Travel(PreRegistrationVM model)
{
    if (TempData["PreRegistrationVM"] != null)
    {
        model = (PreRegistrationVM)TempData["PreRegistrationVM"];
    }
    var newModel = new RegistrationVM(model);
    return View(newModel);
}

在注册过程的每个步骤中从数据库中检索一次信息。

[HttpGet]
public ActionResult Travel(int id)
{
    var model = FooRepository.GetById(id);
    return View(model);
}

我不完全确定为什么 TempData 方法会导致这种情况,对比我提供的理由更博学的人感兴趣。

感谢所有回答的人,帮助我追踪它。

于 2012-04-23T20:24:19.793 回答