与EditorTemplates的MVC3模型绑定问题

时间:2012-04-18 15:03:52

标签: asp.net-mvc-3 post model-binding

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

因此基本的视图模型是:

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

另外3个视图模型的包装器,每个视图模型包含通常的字符串,整数和bool。暂时忽略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'对象始终为null。

模板肯定是渲染,我可以从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'绑定到对象并且(显然)失败。

EDIT2:

[HttpPost]
public ActionResult Travel(RegistrationVM model)

根据要求,我正在发布的行动

EDIT3:

啊......好的回到舞台,这是提供视图的动作方法

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

这就是我一直在使用的(因此已经成为不起作用的过程的一部分)。基本上,先前步骤中的信息保存在TempData中,并在此方法中选取。然后,它用于如上所述实例化VM。此时(如果我在此处插入断点),模型将填充我期望的数据。

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

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

它按预期结合。 TempData是罪魁祸首吗?

1 个答案:

答案 0 :(得分:0)

快速背景调查:这是在创建“向导”逐步注册过程时遇到的问题。我想避免在注册完成之前将信息保存到数据库。因此,我们的想法是使用TempData集合在Actions之间存储信息,并使用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方法导致了这一点,我会对那些比我提供理由更多学习的人感兴趣。

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