【问题标题】:ASP.NET MVC Model split across multiple Partial ViewsASP.NET MVC 模型跨多个局部视图拆分
【发布时间】:2011-01-29 16:15:44
【问题描述】:

我正在开发一个 MVC 3 Razor Web 应用程序,其中存储了多个对象类别的详细信息。 (车辆、房屋、仪器等)。所有对象共享一些公共数据(标题、描述等)和一些特定于它所属类别的详细信息。 Category 列表预计会增长,并且考虑到降低可维护性,我们希望重用相同的 Add Object 向导。该向导基于以下实现。

http://afana.me/post/create-wizard-in-aspnet-mvc-3.aspx

在多步骤向导过程中,最后一步允许用户输入特定类别的详细信息(车辆的型号、品牌、VIN 等)。目前我已经将这最后一步设想为使用 AJAX 的部分视图。因此,我们实际上将拥有多个反映特定类别的部分视图,但共享向导代码的其余部分。

我的通用模型对象是这样的

public class AssetView
{
    [Required]      
    public string Title
     {
        get;
        set;
     }

    [Required]
    public string Description
    {
     get;
      set;
     }

    // Few more generic fields here

    public SpecificAsset AssetDetails { get; set; }
}

复杂属性 AssetDetails 由每种类型的局部视图表示。所以 PartialView "MotorDetails" 将包含一个 MotorAsset 类型的强类型模型,声明如下。

  public class MotorAsset : SpecificAsset
    {
        [Required]
        public string Transmission
        {
            get;
            set;
        }

        [Required]
        public string Make
        {
            get;
            set;
        }
     }

实际的验证非常复杂,但我省略了这些以便更容易理解。

主向导页面声明为

    @model AssetView

  .....

  <div class="wizard-step">
     ....
  </div>
  <div class="wizard-step">
     ....
  </div>
  <div class="wizard-step">
      @{Html.RenderPartial("_MotorCreate", Model.AssetDetails);
  </div>

电机局部视图

 @model MotorAsset

我的问题是如何在这种情况下完成模型验证(或者是否可以使用),因为最后一步不是在视图页面中,而是在部分视图中。

【问题讨论】:

    标签: asp.net-mvc partial-views model-validation


    【解决方案1】:

    您为什么不求助于简单的类继承(OOP 范式)而不是在 AssetView 上拥有一个属性 AssetDetails?

    与其现在拥有的,不如声明

    AssetView(通用属性) -> MotorView 继承 AssetView(具体属性)

    像这样:

    public class AssetView {     
        [Required]           
        public string Title { get; set; }
    
        [Required]
        public string Description     { get; set; }      
    
        // Few more generic fields here
    }
    
    public class MotorView : AssetView {
        ...
    }
    
    @model MotorView    // you still have access to the AssetView's properties in your view and in your controller actions
    

    如果您想保持现在的状态,请使用EditorFor() 并在共享文件夹中创建一个EditorFor 模板并将其强输入MotorAsset(或SpecificAsset,如果您甚至想要它)更通用)。

    然后像这样渲染出来:

    @Html.EditorFor(model=>model.AssetDetails)
    

    这将使控制器能够验证它并将其自动绑定到您的AssetView 中的属性。 高温

    【讨论】:

    • 如果我这样做......我将无法重用向导 UI,我将不得不为每种类型的类别创建一个。
    • 在我看来会更好、更干净、更易于维护。但是,如果您想保持原样,您可以使用 EditorFor() 而不是 RenderPartial() 来解决验证和绑定问题。查看更新的答案。
    • 我们将拥有超过 20 种类型的类别,仅此而已.. 预计会进一步增长,所以它不是不可维护的。我不认为 editorFor 可以使用,因为 "AssetDetails" 的类型是 "SpecificAsset" 。类型会根据使用的类别动态变化。
    • RenderPartial() 不会在文本框(和其他 HTML 输入控件)的 ID 和名称属性前面加上“AssetDetails”。因此自动绑定将失败,随后的验证也将失败。 RenderPartial() 非常适合静态内容,但一段时间以来我一直在转换为 EditorFor() 来渲染编辑子表单。
    • 点了。我不是说我应该使用 RenderPartial(),我只是说使用 EditorFor 不适用于我的场景,因为 Property AssetDetails 被声明为“SpecificAsset”类型,具体取决于添加的对象类型会改变动态到“MotorView”,“HomeView”等,所以如果我在这种情况下使用EditorFor,它会寻找类型为“SpecificAsset”的部分视图,它只是一个空类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多