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

Chr*_*ley 1 asp.net-mvc model-binding asp.net-mvc-4

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

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

这方面的简单例子是

public class TestViewModel

{
    public HierarchyField MyField {get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

@Html.EditorForModel()
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

bindingContext.ValueProvider.GetValue(propertyDescriptor.Name + ".Value")
Run Code Online (Sandbox Code Playgroud)

其中propertyDescriptor.Name +".Value"等同于我在EditorTemplate中有以下事实:

@Html.TextBoxFor(model => model.Value)
Run Code Online (Sandbox Code Playgroud)

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

如果我诚实,整个过程看起来很痛苦,我觉得我错过了一些非常简单的事情.不幸的是,我确实需要这是通用的,因为有很多这些字段,我确实需要这个模型,或类似的字段来处理它们的验证,因为使用DataAnnotation验证属性无法做到这一点.我无法创建与特定视图模型绑定的自定义代码,我宁愿最小化与特定字段关联的代码,更喜欢适用于基类(FieldBase)及其任何子类的内容.

很高兴发布额外的代码,如果有人需要看到它.

Ohl*_*lin 6

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

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

[ComplexType]
public class AccessType
{
  public bool ReadAccess { get; set; }
  public bool EditAccess { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

该模型定义为:

public class UserAccess 
{
  [Key]
  public Int32 UserId { get; set; }
  public AccessType AccessType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我在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)
Run Code Online (Sandbox Code Playgroud)

我在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) 
Run Code Online (Sandbox Code Playgroud)

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

对于_CreateOrEdit.cshtml文件,我添加了这一行来渲染复杂类型部分:

@Html.EditorFor(m => m.AccessType)
Run Code Online (Sandbox Code Playgroud)

...到Delete.cshtmlDetails.cshtml我添加了:

@Html.DisplayFor(m => m.AccessType)
Run Code Online (Sandbox Code Playgroud)

...和Index.cshtml我添加了:

@Html.DisplayFor(_ => item.AccessType)
Run Code Online (Sandbox Code Playgroud)

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

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