【问题标题】:ASP.NET MVC 4 - Complex Types and Model Binding/RenderingASP.NET MVC 4 - 复杂类型和模型绑定/渲染
【发布时间】:2013-05-26 04:17:39
【问题描述】:

我已经看到了许多与此类似的问题,但似乎没有一个答案比我已经得到的更进一步。

我有一个 ViewModel,它包含一些复杂的类型,这些类型代表某些股票 UI 控件并附加了一些验证逻辑。我需要将这些渲染到基于 EditorTemplate/DisplayTemplate 的页面,并且还需要在提交表单时正确绑定属性,以便开发人员可以在其控制器等中使用视图模型。

简单的例子是

public class TestViewModel

{
    public HierarchyField MyField {get; set; }
}

最简单的是,我需要开发人员能够使用简单的方法为这个视图模型创建一个编辑器

@Html.EditorForModel()

对于 HierarchyField 的任何可编辑部分,要在该类型的自定义 EditorTemplate 中设置字段。

我已经通过使用自定义 MetaDataProvider 并覆盖 IsComplexType 来允许它进行渲染,虽然这不是我完全熟悉的东西,但确实可以完成这项工作。该解决方案的详细信息在这里 (http://blogs.msdn.com/b/stuartleeks/archive/2010/04/01/collections-and-asp-net-mvc-templated-helpers-part-3.aspx?Redirected=true)

我现在一直在尝试获取模型绑定以在提交表单时更新属性,并调用 HierarchyField 类上的方法来执行一些自定义验证并根据调用结果更新 ModelState。

我首先创建了一个 DefaultModelBinder 的子类,该子类在 BindProperty 覆盖中具有逻辑,以检查被绑定的属性是否属于这种类型。到目前为止一切都很好。当我想调用采用预期值并尝试验证该值的实例方法时,问题就来了。 BindProperty 方法给了我一个 PropertyDescriptor 的实例,它允许我找到关于我的属性的元数据,以及一个带有 ValueProvider 的 BindingContext,它允许我读取值,但是,没有从以下位置返回我的复杂类型的实例:

bindingContext.ValueProvider.GetValue(propertyDescriptor.Name + ".Value")

propertyDescriptor.Name + ".Value" 等同于在我的 EditorTemplate 中我有以下内容:

@Html.TextBoxFor(model => model.Value)

而不是类型,因为我显然只在回发的字段中获得了对 Value 属性的引用,所以我得到了一个 String[]。我假设,要让它工作,我需要为 HierarchyField 注册某种 ValueProvider,但理想情况下我正在寻找更通用的东西,因为我有许多这些类型要设置,所有其中子类是一个通用抽象类型(它们都有一个名为“Value”的属性,它返回其值的字符串表示形式)。

老实说,整个过程似乎很痛苦,以至于我觉得我错过了一些非常简单的事情。不幸的是,我确实需要它是通用的,因为有几十个这样的字段,而且我确实需要这个模型,或者类似的东西来处理它们的字段验证,因为 DataAnnotation 验证属性无法做到这一点。我无法创建与特定视图模型相关联的自定义代码,我希望尽量减少与特定字段相关联的代码,更喜欢适用于基类 (FieldBase) 及其任何子类的代码。

如果有人需要,很乐意发布其他代码。

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4 model-binding


    【解决方案1】:

    我一直在几个项目中使用复杂类型和自定义渲染,没有任何问题。也许我误解了你的问题,但我想我可以发布一个简化的工作示例(MVC4),也许它会帮助你。

    在我的示例中,复杂类型定义为:

    [ComplexType]
    public class AccessType
    {
      public bool ReadAccess { get; set; }
      public bool EditAccess { get; set; }
    }
    

    模型定义为:

    public class UserAccess 
    {
      [Key]
      public Int32 UserId { get; set; }
      public AccessType AccessType { get; set; }
    }
    

    我在 Views\Shared\DisplayTemplates 中创建了以下 显示模板,名为 AccessType.cshtml 来处理复杂类型的呈现当它被显示时。

    @model [path to complex type].AccessType
    @Html.LabelFor(m => m.EditAccess,"Read access")
    @Html.DisplayFor(m => m.ReadAccess) 
    @Html.LabelFor(m => m.EditAccess, "Edit access")
    @Html.DisplayFor(m => m.EditAccess)
    

    我在 Views\Shared\EditorTemplates 中创建了以下 编辑模板,名为 AccessType.cshtml 来处理复杂类型的呈现编辑时。

    @model [path to complex type].AccessType
    @Html.LabelFor(m => m.ReadAccess,"Read access")
    @Html.CheckBoxFor(m => m.ReadAccess) 
    @Html.LabelFor(m => m.EditAccess, "Edit access")
    @Html.CheckBoxFor(m => m.EditAccess) 
    

    对于使用这种复杂类型的模型的视图文件,我进行了以下更改:

    在 _CreateOrEdit.cshtml 文件中,我添加了这一行来呈现复杂类型部分:

    @Html.EditorFor(m => m.AccessType)
    

    ...到 Delete.cshtml 和 Details.cshtml 我已添加:

    @Html.DisplayFor(m => m.AccessType)
    

    ...以及 Index.cshtml 我已添加:

    @Html.DisplayFor(_ => item.AccessType)
    

    这就是我渲染和使用复杂类型所需的全部内容。

    如果您的问题更复杂,请添加更多代码来说明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-28
      • 1970-01-01
      • 2023-03-18
      相关资源
      最近更新 更多