2012-12-09 26 views
0

我有一个Web应用程序,我想在其中显示测试对象的表单。不同的测试实例可以有不同的模式。我可以很好地显示它,但它不会将表单中的所有数据填充到我的模型中。为什么MVC 2中的ViewModel子对象为空?

这里是我的模型类:

public class EnterTestData 
{ 
    public string StudyId { get; set; } 
    public Test Test { get; set; } 
} 

public sealed class Test 
{ 
    public string Identity { get; set; } 
    public string Name { get; set; } 
    public IEnumerable<TestField> Fields { get; set; } 
} 

public sealed class TestField 
{ 
    public string Identity { get; set; } 
    public string Name { get; set; } 
    public string Value { get; set; } 
    public string Type { get; set; } 
} 

这里是我查看相关部分:

<% Html.BeginForm("PostTestData", "StudiesUserInterface"); %> 
<table> 
    <% 
     foreach (var testField in Model.Test.Fields) 
      Html.RenderPartial("UserControls/TestFieldUserControlascx", testField); 

     foreach (var category in Model.Test.Categories) 
     { 
    %> 
    <tr> 
     <td colspan="2" style="font-style: italic; text-align: center;"> 
      <%=category.Name %> 
     </td> 
    </tr> 
    <% 
      foreach (var testField in category.Fields) 
       Html.RenderPartial("UserControls/TestFieldUserControlascx", testField); 

     } 
    %> 
    <tr> 
     <td colspan="2" style="text-align: right;"> 
      <input type="submit" name="newsletter" value="Enter Result" /> 
     </td> 
    </tr> 
</table> 
<% Html.EndForm(); %> 

而对于实际的文本框的局部视图:

<tr> 
    <td> 
     <%= Model.Name %> 
    </td> 
    <td> 
     <% 
      switch (Model.Type) 
      { 
       case "date": 
       case "text": 
       case "number": 
     %> 
     <%= Html.TextBox(Model.name, Model.Value) %> 
     <% break; 
       default: %><%= Html.Label("Unknown data type") %><% break; 
      } 
     %> 
    </td> 
</tr> 

更新控制器方法:

public ActionResult EnterTestData(string studyId, string testId) 
    { 
     var testDefinition = ServiceKitLocator.GetStudyService().GetTestDefinition(testId); 

     return View(new EnterTestData { StudyId = studyId, Test = testDefinition }); 
    } 

    public ActionResult PostTestData(EnterTestData model) 
    { 
     //I'm just putting a break point here and checking the model in the debugger for now 
     return RedirectToAction("Index"); 
    } 

问题是,Test返回到我的控制器时为空。我如何获得它填充?为什么它是空的?

+0

您是否也可以显示您的控制器操作方法? – Sampath

+0

完成。另外,我意识到我的部分视图中的TextBox定义不好,所以我也更新了它。 – tallseth

+0

作为一种最佳实践,您总是尝试为您的操作方法提供[HttpGet]或[HttpPost]。要了解哪个是获取和发布的内容非常困难。 – Sampath

回答

0

我认为问题是Html.TextBox元素。 如果您的视图中的模型是“测试”类型是正确的,但是在您的控制器操作中您想要绑定到类型为“测试”属性“EnterTestData”的类型 那么您的TextBox应该是初始化像

Html.TextBox("Test.Name", Model.Value) 

重要的部分是name参数。模型绑定器将此名称与您的发布操作中模型类型的属性相匹配,在您的情况“EnterTestData”中。

您还可以使用编辑器模板视图。这与你的局部视图相同。 在您的项目中,转到Views \ Shared \并创建一个名为EditorTemplates的文件夹(如果不存在)。 在此文件夹中创建一个局部视图并将其命名为模板应该用于的类/类型。在你的情况“TestField.ascx”。其实你可以复制和重命名你现有的局部视图。 在你,你有主视图改变两两件事: - 使用替代的foreach - 调用编辑模板在循环 这样的:

for(int i = 0; i < Model.Test.Fields.Count(); i++) 
      Html.EditorFor(Model => Model.Test.Fields[i]); 

在你必须改变一件事模板视图: - 用户TextBoxFor而不是使用TextBox 像:

Html.TextBoxFor(Model => Model.Value) 

我经常使用这种模式。它可以很容易地绑定复杂的模型。 您可能会看看生成的HTML

+0

谢谢@ developer10214。我最终通过编写一个自定义IModelBinder来解决这个问题,并且即将发布该答案。但是,由于这更加明确地解决了我所问的问题,我将在明天进行测试,看看它是否有效。 – tallseth