Asp.net mvc ASP.NET MVC 4-复杂类型和模型绑定/呈现

Asp.net mvc ASP.NET MVC 4-复杂类型和模型绑定/呈现,asp.net-mvc,asp.net-mvc-4,model-binding,Asp.net Mvc,Asp.net Mvc 4,Model Binding,我见过许多类似的问题,但似乎没有一个答案能让我走得更远 我有一个ViewModel,它包含一些表示某些股票UI控件的复杂类型,并附加了一些验证逻辑。我需要让它们呈现到基于EditorTemplate/DisplayTemplate的页面上,还需要在提交表单时正确绑定属性,以便开发人员可以在其控制器内使用视图模型等 这方面的一个简单例子是 public class TestViewModel { public HierarchyField MyField {get; set; } }

我见过许多类似的问题,但似乎没有一个答案能让我走得更远

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

这方面的一个简单例子是

public class TestViewModel

{
    public HierarchyField MyField {get; set; }
}
最简单的是,我需要开发人员能够使用简单的

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

通过使用自定义MetaDataProvider和重写IsComplexType,我已经实现了这种渲染,尽管我对它不是很熟悉,但它确实可以完成这项工作。有关该解决方案的详细信息,请参见此处

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

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

bindingContext.ValueProvider.GetValue(propertyDescriptor.Name + ".Value")
其中propertyDescriptor.Name+.Value等同于在我的EditorTemplate中有以下内容:

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

老实说,整个过程似乎很痛苦,我觉得我错过了一些简单的事情。不幸的是,我确实需要这是通用的,因为有几十个这样的字段,而且我确实需要这个模型,或者类似的模型来处理字段的验证,因为这大部分不能通过DataAnnotation验证属性来完成。我不能创建绑定到特定视图模型的自定义代码,我更喜欢最小化绑定到特定字段的代码,更喜欢应用于基类FieldBase及其任何子类的代码


如果有人需要的话,我很乐意发布额外的代码。

我在一些项目中使用了复杂类型和自定义渲染,没有任何问题。也许我误解了你的问题,但我想我可以发布一个简化的工作示例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)
…要删除.cshtml和Details.cshtml,我添加了:

@Html.DisplayFor(m => m.AccessType)
@Html.DisplayFor(_ => item.AccessType)
…在Index.cshtml中,我添加了:

@Html.DisplayFor(m => m.AccessType)
@Html.DisplayFor(_ => item.AccessType)
这就是渲染和使用复杂类型所需的全部内容


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

我在一些项目中使用了复杂类型和自定义渲染,没有任何问题。也许我误解了你的问题,但我想我可以发布一个简化的工作示例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)
…要删除.cshtml和Details.cshtml,我添加了:

@Html.DisplayFor(m => m.AccessType)
@Html.DisplayFor(_ => item.AccessType)
…在Index.cshtml中,我添加了:

@Html.DisplayFor(m => m.AccessType)
@Html.DisplayFor(_ => item.AccessType)
这就是渲染和使用复杂类型所需的全部内容

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