ASP.NET MVC 4 - 复杂类型和模型绑定/渲染

时间:2013-05-30 14:22:22

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

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

我有一个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)及其任何子类的内容。

如果有人需要查看附加代码,请尽快发布。

1 个答案:

答案 0 :(得分:6)

我在一些项目中使用复杂类型和自定义渲染没有任何问题。也许我误解了你的问题,但我想我可以发布一个简化的工作示例(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; }
}

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

@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)

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

@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)

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

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