如何添加元数据来动态建立MVC3视图模型? [英] How to add MetaData to a dynamically build MVC3 ViewModel?

查看:200
本文介绍了如何添加元数据来动态建立MVC3视图模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

其中的一个项目,我工作的主要特点是用户配置形式(如表单填写时)的基础上pre-现有的字段类型池(的能力众所周知类型,比如用户名,出生日期等也是泛型类型喜欢串,日期时间等)。

One of the key features of a project I'm working on is the ability for the user to configure Forms (as in "Forms" to fill-up) based on a pool of pre-existing field types (well known types, for instance "user name", "date of birth" etc. but also "generic types" like "string", "DateTime" etc.).

我们曾经有过,对于众所周知的类型正常工作静态视图模型,看起来像这样的:

We used to have a static ViewModel that worked fine for the "well known" types and looked like this:

public class UserInputModel
{
    [StringLength(200)]
    public string Name { get; set; }

    [Required(ErrorMessageResourceName = "BirthDateEmptyError", ErrorMessageResourceType = typeof(Resources.ErrorMessages))]
    public DateTime BirthDate { get; set; }

    //Here comes a lot of other properties
}

所有已知的性能上市我们显示或隐藏他们给出的上下文。

All the known properties were listed and we were showing or hiding them given the context.

但最后一个要求来了,改变了这一切。现在的用户应能够为他想添加尽可能多的泛型类型的字段。为了做到这一点,我们决定让这个InputModel完全动态的。现在看起来是这样的:

But the last requirement came and changed all that. The user shall now be able to add as many generic type fields as he wants. In order to do this, we decided to make this InputModel entirely dynamic. It now looks like this:

public class UserInputModel
{
    // Each ModelProperty has an "Id" and a "Value" property
    public ICollection<ModelProperty> Properties { get; set; }
}

这就像一个魅力。剃刀视图只需要遍历集合,创建相应的控件以超过标准的方式集合的每个属性:

This works like a charm. The razor view only has to iterates over the collection, create the corresponding controls for each property of the collection in a more than standard way:

@Html.TextBoxFor(m => m.Properties[index].Value);

...我们很好地取回数据作为填好的表格。

... and we nicely get the data back as a filled form.

=>这工作得很好,但我们没有任何客户端验证。对于这一点,我们需要一些元数据......我们不通过注解再有,因为我们动态创建的模型。

=> This works fine, but we don't have any client-side validation. For this, we would need some Metadata... which we don't have via annotations anymore since we're dynamically creating the model.

为了提供这些元数据,我创建了一个 CustomModelMetadataProvider DataAnnotationsModelMetadataProvider 继承,并把它注册为新 ModelMetadataProvider 在Global.asax。在 CreateMetadata()函数被创建后视图模型的调用,并为每个我的ViewModel的属性... SOFAR那么好了。

In order to provide those MetaData, I created a CustomModelMetadataProvider that inherits from DataAnnotationsModelMetadataProvider and registered it as the new ModelMetadataProvider in the Global.asax. The CreateMetadata() function gets called upon creation of the ViewModel, and that for each of the properties of my ViewModel... sofar so good.

问题出在哪里开始:为了一些元数据添加到当前的财产,我首先需要确定哪些财产我目前在看(姓名具有200最大长度,日期诞生还没有,所以我不能指定一个最大长度为每默认每个属性)。而somewhow我没能做到这一点,因为没有所有属性具有相同的名称和相同的容器类型 ModelProperty

Where the problem starts: in order to add some metadata to the current property, I first need to identify which property I am currently looking at ("Name" has a maxlength of 200, "date of birth" hasn't so I cannot assign a maxlength to every property per default). And somewhow I didn't manage to do that yet since all the properties have the same name Value and the same container type ModelProperty.

我试图访​​问通过反射属性的容器,但由于ModelAccessor的目标是视图模型本身(因为拉姆达前pression的 M =&GT; m.Properties ),下面的结构给我的视图模型作为一个整体,而不仅仅是ModelProperty:

I tried accessing the container of the property via reflection, but since the ModelAccessor's target is the ViewModel itself (because of the lambda expression m => m.Properties), the following construct gives me the ViewModel as a whole, not just the ModelProperty:

var container = modelAccessor.Target.GetType().GetField("container");
var containerObject = (UserInputModel)container.GetValue(modelAccessor.Target);

我已经一遍又一遍地翻这一点,但无法找到一个方法来确定哪些ModelProperty我手上。有没有办法做到这一点?

I've been flipping this over and over but cannot find a way to identify which ModelProperty I have in hand. Is there a way to do this?

更新:在每个可能的方向一会儿翻转在此之后,我们终于走了另一条途径。我们基本上是使用JavaScript的unobstrusive而不触及属性也没有元数据使用MVC的验证能力。总之,我们添加HTML属性,如值数据=真正的(和所有其他所需的属性)在 @ Html.TextBoxFor()语句。这种奇妙的作品为所有的原子验证(需要stringlength等)。

Update: after flipping this in every possible direction for a while, we finally went another way. We are basically using unobstrusive javascript to use MVC's validation capabilities without touching attributes nor metadata. In short, we add HTML attributes like value-data="true" (and all other required attributes) to the @Html.TextBoxFor() statements. This works wonderfully for all the atomic validations (required, stringlength etc.).

推荐答案

看看这篇文章可以帮助您:<一href=\"http://stackoverflow.com/questions/9989785/technique-for-carrying-metadata-to-view-models-with-automapper\">Technique携带的元数据视图模型与AutoMapper 。

See if this article help you: Technique for carrying metadata to View Models with AutoMapper.

也可以使用这个的想法(自定义模型元数据提供者):<一href=\"http://stackoverflow.com/questions/8629064/changing-viewmodels-metadatatype-attribute-at-runtime\">changing在运行时视图模型的MetadataType属性

Also use this one for ideas (custom model metadata provider): changing viewmodel's MetadataType attribute at runtime

流利的验证可能是你在我心中的最佳选择,但它显然达您可以选择上面之间的最佳匹配。

Fluent validation is probably the best option for you in my mind, but its obviously up to you to select the best match among those above.

更新

尝试使用 ModelMetadata 并重写 ModelMetadataProvider 下潜深成MVC:ModelMetadata和ModelMetadataProvider 。这样,您完全自定义模型元数据(这将替换数据注解),你对正在发生的事情,而不是依赖于ASP.NET MVC的完全控制。

Try use ModelMetadata and override ModelMetadataProvider: Dive Deep Into MVC: ModelMetadata and ModelMetadataProvider. This way you completely customize your model metadata (this replaces data annotations) and you have complete control on what is happening, rather than relying on ASP.NET MVC.

另外一个好地方,看它是<​​一个href=\"http://buildstarted.com/2010/09/14/creating-your-own-modelmetadataprovider-to-handle-custom-attributes/\"相对=nofollow>创建自己的ModelMetadataProvider自定义属性的处理。

Another good place to look at it is Creating your own ModelMetadataProvider to handle custom attributes.

希望这一切都是对你有所帮助。

Hope this all is of help to you.

这篇关于如何添加元数据来动态建立MVC3视图模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆