MVC4:嵌套的部分视图丢失了模型数据

时间:2013-08-27 08:04:30

标签: c# asp.net-mvc-4 viewmodel partial-views

在MVC4项目中,使用ViewModel的部分View,并在其上有一个GET表单。在Controller操作中,我期望ViewModel对象包含一些数据。 当此部分放在普通(.cshtml)视图上时,我通过Controller操作中预期的ViewModel对象接收数据。但是,当此部分位于 另一个部分视图 时,由于某种原因,控制器操作中的ViewModel对象为空。当我逐步创建HttpGet表单时,传入的模型不为空,但是当调用GET控制器操作时,模型就是。

有人知道这个的原因吗?这是一些我不知道的MVC行为吗?谢谢!

偏见:

@model ViewModel
    @if (Model != null)
    {
        using (Html.BeginForm("DoSomething", "Home", FormMethod.Get))
        { 
            @Html.HiddenFor(m => m.Object)            
            <input id="btnSend" type="submit"> 
        }
    }

其他部分:

@using OtherViewModel.ViewModel
@Html.Partial("The Partial", Model.ViewModel, ViewData)

视图:

@Html.Partial("_TheOtherPartial", Model.OtherViewModel, new ViewDataDictionary(ViewData) {
                TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "prefix" }
    })

控制器

[HttpGet]
[AllowAnonymous]
public ActionResult DoSomething(ViewModel data)
{
}

2 个答案:

答案 0 :(得分:5)

在这里你应该考虑两件事。第一个是尽量不在部分视图中放置表单。如果您这样做,最终可能会出现嵌套表单,浏览器不支持这些表单,因为it's not valid HTML

<!ELEMENT FORM - - (%block;|SCRIPT)+ -(FORM) -- interactive form -->

-(FORM)构造不允许嵌套表单。

第二件事是代替部分观点我建议您使用编辑器模板Take a look here如何使用它们。接下来,正如我之前所说,尝试将表单保留在编辑器模板之外 - 使用主视图中的表单,让编辑器模板呈现页面的不同部分。这样可以减少混乱,并使代码更清晰。

在您的具体示例中,它可能如下所示:

主要观点:

@model MainModel
@using (Html.BeginForm("YourAction", "YourController"))
{ 
    @Html.EditorFor(m => m.OtherViewModel)
    <input id="btnSend" type="submit"> 
}

OtherViewModel.cshtml编辑器模板:

@model OtherViewModel
@Html.EditorFor(m => m.ViewModel)

ViewModel.cshtml编辑器模板:

@model ViewModel
@Html.EditorFor(m => m.Object)

主控制器:

public ActionResult YourAction(MainModel data)
{
    ...

型号:

public class MainModel
{
    public MainModel() { OtherViewModel = new OtherViewModel(); }
    public OtherViewModel OtherViewModel { get; set; }        
}

public class OtherViewModel
{
    public OtherViewModel() { ViewModel = new ViewModel(); }
    public ViewModel ViewModel { get; set; }
}

public class ViewModel
{
    public string Object { get; set; }
}

请注意,模板名称反映了模型类型名称。接下来,将模板放在此~/Views/Shared/EditorTemplates/或此~/Views/YourController/EditorTemplates/目录下。

答案 1 :(得分:-1)

或者,您可以将与“视图”中获得的原始模型相同的模型传递给“其他部分”,并再次传递给“部分”,同时使用所需部分仅对应的视图。