2012-02-13 36 views
1

我有基于ASP.Net MVC3的Web应用程序。我需要一个“创建”视图,它不会知道模型类型,直到用户从下拉列表中选择要创建的子类型。为了试图解决这个问题,我为每个派生模型类型在Shared/EditorTemplates下创建了一个编辑器模板。这允许我创建一个强制类型为视图模型的“Create.cs”。视图模型只有两个成员,一个枚举和一个复杂类型。这个想法是,视图最初只显示一个下拉菜单(enum成员的编辑器),然后当用户最初提交指定的“模型类型”(下拉选定值)时,POST操作可以检查“模型类型“为视图模型的单个复杂成员指定并实例化正确的派生模型类型,其类型是所有可能的”模型类型“的基本类型。即使设置了属性并且有效,TryUpdateModel为什么返回false?

抽象+派生类型的模型对象...

public abstract class MyModelBase 
{ 
    public MyModelType_e ModelType {get; set; } 
    [Required] 
    public string Name { get; set; } 
} 

public class DerivedType1 : MyModelBase 
{ ... } 

public class DerivedType2 : MyModelBase 
{ ... } 

public class DerivedType3 : MyModelBase 
{ ... } 

我有一个复杂的视图模型如下...

public enum MyModelType_e 
{ 
    DerivedType1 = 0, 
    DerivedType2 = 1, 
    DerivedType3 = 2 
} 

public class MyModelCreate 
{ 
    public MyModelType_e ModelTypeForSelectList { get; set; } 
    public MyModelBase ModelBase { get; set; } 
} 

我的GET控制器操作实例化了上述观点的型号为视图,即只显示基于MyModelType_e enum的项目显示的下拉列表+模型的“ModelBase”属性的值最初为空。所以GET操作方法是这样的......

[HttpGet] 
public ActionResult Create() 
{ 
    return View(new MyModelCreate()); 
} 

注意,在帽的下面评论关于我的问题的症结是在于TryUpdateModel失败(见下文),即使这台模型库的属性(派生型)成员按预期相应的表单值...

[HttpPost] 
public ActionResult Create(MyModelCreate model) 
{ 
    if (model.ModelBase == null || 
     (int)model.ModelTypeForSelectList != model.ModelBase.ModelType) 
    { 
     switch (model.ModelType) 
     { 
      case MyModelType_e.DerivedType1: 
       model.ModelBase = new DerivedType1(); 
       break; 
      case MyModelType_e.DerivedType2: 
       model.ModelBase = new DerivedType2(); 
       break; 
      case MyModelType_e.DerivedType3: 
       model.ModelBase = new DerivedType3(); 
       break; 
     } 
     return View(model); 
    } 

    if (!TryUpdateModel(model.ModelBase)) 
     return View(model); // <<< THIS HAPPENS EVEN THOUGH ModelBase APPEARS TO BE UPDATED PROPERLY... 
    // For instance, I can see right here with intellisense that model.ModelBase.Name 
    // is NOT null or empty but rather is truly updated with the correct form value(s)... 

    // TODO: Insert the record, etc... (currently we never get here...) 
} 

所以上面的部分是哪里出了问题源于但这里是我的看法,以帮助了解...

@model MyNamespace.MyModelCreate 

<h2>Create</h2> 

... 

@using (Html.BeginForm()) 
{ 
    @Html.ValidationSummary(false) 
    <fieldset> 
    <legend>Input</legend> 
    <div class="editor-label"> 
    @Html.Label("Select Model Type") 
    </div> 
    <div> 
    @Html.EnumDropDownListFor(model => model.ModelType) 
    @Html.ValidationMessageFor(model => model.ModelType) 
    </div> 

    @* 
    Conditionally show the correct editor template... 
    There is one existing under ../Shared/EditorTemplates for each 
    derived type (DerivedType1, DerivedType2, DerivedType3, etc...) 
    This much is working in the sense that the correct editor fields 
    are displayed based on what the user selects in the above drop-down. 
    *@ 
    @if (Model.InputModel != null) 
    { 
     @Html.EditorFor(model => model.ModelBase); 
    } 

    <p> 
     <input type="submit" value="Continue" /> 
    </p>    
    </fieldset> 
} 

因此,一旦初始POST(模型类型被选中),我的POST动作方法会通过设计进入TryUpdateModel行,但由于某种原因验证失败。虽然我可以清楚地看到TryUpdateModel在视图模型的ModelBase成员上正确设置Name运算,但我真的不明白的部分是验证摘要报告“Name is required”。

我非常感谢这里的任何帮助或指导......我对ASP.NET MVC相当陌生,我愿意以不同的方式做事,因为我明白可能有其他方法可以设计我的请求/操作+意见来完成这个“多步骤”的问题,但我真的只是去我为什么喜欢处理派生模型类型的EditorTemplate方法,最简单的可能的事情等

在此先感谢...

+0

在你的MyModelCreate类中,你似乎正在使用一些你没有显示的MyModelBase类型。你能否展示它的定义? – 2012-02-14 07:36:26

+0

Darin,谢谢你的提醒......我错误地重命名了一些东西(修复了我的最后一次编辑)。我实际上最近解决了这个问题,但还没有找到时间发布我自己的答案:( – blins 2012-03-19 14:32:57

回答

0

我的解决方案基本上涉及增加两个额外的控制器操作(GET和POST)。我在强烈类型的(../Shared/EditorTemplates)下创建了单独的视图(每个派生模型类型一个)。这样,初始的“创建”POST动作只接收选定的类型(模型只是一个指定所需类型的枚举值),然后重定向到另一个控制器动作,如“CreateByType”,它获取请求的具体类型的新实例并返回正确的编辑视图。额外的“CreateByType”控制器操作(GET和POST)只需要处理抽象基础,因为它从服务层请求实例(传递枚举值)。然后,我所要做的就是在EditorTemplates下为每个具体类型创建一个视图。

1

检查ModelState。在运行TryUpdateModel之后应该设置错误。 我不得不从某些属性中删除Required属性。

相关问题