如何在 ASP.NET MVC 中提供自己的 ICustomTypeDescriptor?

发布于 2024-11-03 00:32:17 字数 1293 浏览 7 评论 0原文

我正在为 ASP.NET MVC 3 开发一个小型库,该库应该提供更好的模型元数据可重用性以及从数据实体到自定义视图模型的轻松映射。为此,我需要能够为 ASP.NET MVC 中三个不同的感兴趣领域提供我自己的 ICustomTypeDescriptor 实现:

  1. 脚手架
  2. 验证
  3. 模型绑定

这似乎可以通过设置 System.Web.Mvc.ModelMetadataProviders.Current 来完成 到我自己的 CustomMetaDataProvider,但这还不足以涵盖上述所有三点。

问题是 System.Web.Mvc 中有几个类直接调用这个 System.Web.TypeDescriptorHelper ,它是不可扩展的,因为它看起来像这样:

internal static class TypeDescriptorHelper {
        public static ICustomTypeDescriptor Get(Type type) {
            return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
        }
    } 

我发现的唯一解决方案非常尴尬并且需要从 System.Web.Mvc 继承许多类型才能使其工作。我什至不得不完全重新实现 CustomModelBinderDictionary 只是为了覆盖一两行代码。所以它可以工作,但这是一个非常混乱的 hack,并且可能会在我下次更新到新的 ASP.NET MVC 版本时崩溃。

这就是我想知道的:我是否错过了任何简单的方法来做到这一点?

额外问题:如果没有,并且您来自 MVC 团队,您是否可以考虑在 MVC 4 中创建适当的扩展点;-)?

编辑:回答为什么我需要编写自己的 TypeDescriptor 的问题:有几个原因: 1.最重要的是:我需要解决 https://forums.asp 中描述的问题.net/t/1614439.aspx/1 2.另外,由于各种原因,我需要动态插入元数据。例如,我想编写自己的 Bind 属性代码,但 BindAttribute 是密封的。因此,在检测我自己的绑定属性实现时,我不是从它派生,而是从 TypeDescriptor 动态发出匹配的 BindAttribute。

I'm working on a small library for for ASP.NET MVC 3 that should offer better reusability of model metadata and easy mapping from data entities from / to custom viewmodels. For this I need to be able to provide my own implementation of ICustomTypeDescriptor for three different areas of interest in ASP.NET MVC:

  1. Scaffolding
  2. Validation
  3. Modelbinding

It seems like this could be done by setting System.Web.Mvc.ModelMetadataProviders.Current to my own CustomMetaDataProvider, but this is not nearly enough to cover all three points above.

The problem is that there are several classes in System.Web.Mvc which call directly into this System.Web.TypeDescriptorHelper which is not extensible because it looks like this:

internal static class TypeDescriptorHelper {
        public static ICustomTypeDescriptor Get(Type type) {
            return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
        }
    } 

The only solution I found is very awkward and required subclassing lots of types from System.Web.Mvc to make it work. I even had to re-implement CustomModelBinderDictionary completely only to overwrite one or two lines of code. So it works, but it is a very messy hack and likely to break the next time I update to a new ASP.NET MVC version.

So here's what I like to know : Did I miss any simple way to do this?

Bonus question: If not and you are from the MVC team, could you consider creating an appropriate extensibility point in MVC 4 ;-)?

Edit: In reply to the question why I need to code my own TypeDescriptor: There are several reasons for this:
1. Most important: I need a workaround for the problem described at https://forums.asp.net/t/1614439.aspx/1
2. Also, I need to insert metadata dynamically for various reasons. For example I want to code my own Bind attribute, but BindAttribute is sealed. So instead of deriving from it, I am emitting a matching BindAttribute dynamically from the TypeDescriptor when detecting my own bind attribute implementation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

人间☆小暴躁 2024-11-10 00:32:17

根据 Brad Wilson(ASP.NET MVC 团队成员)的说法,此问题已被列入错误列表MVC 4。所以目前似乎没有好的解决方案,但希望当 MVC 4 出来时这个问题能够得到解决。

对于任何对我的可重用验证和脚手架元数据以及模型/视图模型映射库感兴趣的人,请随时订阅我的博客 https: //devarmind.wordpress.com/。我将在那里发布该库。

According to Brad Wilson (an ASP.NET MVC team member) this issue has been put on the bug list for MVC 4. So it seems there is no good solution for the moment, but hopefully this will be solved when MVC 4 comes out.

For anyone interested in my library for reusable validation and scaffolding metadata and model / viewmodel mapping, feel free to subscribe my blog at https://devermind.wordpress.com/. I'm going to release the library there.

夜访吸血鬼 2024-11-10 00:32:17

我不确定您尝试使用 Validation、ModelBinding 和潜在的 ModelMetadata 的自定义实现来做什么,而这不能通过 MVC 中的 DependencyResolver 功能来完成?

最近的 MVC 3 工具更新中新的脚手架支持可能会满足您对脚手架的需求;不过,我会考虑是否可以连接到 ModelBinding、ModelMetadata 和 Validation 的 DependencyResolver 功能,看看它们是否可以实现您正在寻找的功能。我最近遇到了类似的情况,我需要从头开始实现许多这些行为以提供灵活的框架,并且我只需使用 IoC 的 ModelMetadata 和 Validation 提供程序就可以做到这一点。在某些情况下,我最终还继承了 DynamicObject(或 ExpandoObject),以提供更大的灵活性。我知道这并不是一个直接的答案,但我不确定为什么您需要访问低于这些可扩展性点的任何内容?

编辑:如果您希望在类似的 ViewModel 上重用 ModelMetadata 以避免在多个位置重新定义相同的 ModelMetadata,您可能需要考虑这一点的含义。很多时候,您希望对实体进行某些数据限制,但这些限制应该针对 DataModel 而不是 ViewModel。用户可能有稍微更严格的规则。例如,您可以规定 ViewModel 中的某些字段对于用户来说是只读的,但用作 DataModel 的实体允许您修改值(通常在代码中)。同样,您可能会遇到这样的情况:用于为 VideModel 生成“创建”视图的 ModelMetadata 可能与用于“编辑”视图的 ViewModel 略有不同。重用它们似乎是保持一致性和减少代码重复的好方法,但这可能是您以后后悔的事情。我最近遇到了同样的问题,我想避免为每个可能导致回发的视图编写一个新的 ViewModel,我还没有找到我喜欢的完美解决方案,但我认为重用 ModelMetadata 会导致更多它可能解决的问题我的意见。为需要它们的视图编写 ViewModel 也可能会消除您实现自定义 BindAttribute 实现的需要和脚手架问题。
如果我正确地假设不想使用自己的元数据创建这么多 ViewModel 是导致您尝试查找自定义 BindAttribute、自定义脚手架、自定义 ModelMetadata、自定义验证和自定义 ModelBinding 的实现的原因...这可能是值得的查看创建 ViewModel 实际上需要多少时间。

如果您找到更好的方法,请随时告诉我:-)

I'm not sure what it is that you're trying to do with custom implementations of Validation, ModelBinding and potentially ModelMetadata, that can't be done with the DependencyResolver functionality in MVC?

The new scaffolding support in the recent Tooling Update for MVC 3 may meet your needs for scaffolding; however I would take a look at possibly hooking into the DependencyResolver functionality for the ModelBinding, ModelMetadata and Validation and see if they can achieve what you are looking for. I had a similar situation recently where I needed to implement a lot of these behaviors from scratch to provide a flexible framework, and I was able to do so with just ModelMetadata and Validation providers using IoC. I also ended up inheriting DynamicObject (or ExpandoObject) in a few cases to give even more flexibility. I know this isn't exactly a direct answer but I'm not sure why you would need access to anything lower than these extensability points?

EDIT: If you're looking to reuse ModelMetadata on similar ViewModels to avoid having to redefine the same ModelMetadata over in multiple places, you might want to consider the implications of this. There are many times when you want certain data restrictions on your entities but these restrictions should be on the DataModel and not the ViewModel. The user may have a slightly more restrictive rules. For example, you may stipulate that certain fields are readonly for the user in the ViewModel, but that the entity used as a DataModel does allow you to modify the value (typically from within your code). Similarly you may run into situations where the ModelMetadata used to generate the Create view for the VideModel might be slightly different than the ViewModel used for the Edit view. Reusing them may seem like a great way to stay consistent and reduce code duplication but it may be something you regret later on. I recently ran into the same issue where I wanted to avoid writing a new ViewModel for each view that may cause a postback, I haven't found a perfect solution I like but I think reusing the ModelMetadata will cause more problems that it might solve in my opinion. Writing ViewModels for views that need them will also probably eliminate your need to implement a custom BindAttribute implementation and the Scaffolding issue.
If I'm right in assuming not wanting to create so many ViewModels with their own Metadata is what's causing you to try and find implementations of a custom BindAttribute, custom Scaffolding, custom ModelMetadata, custom Validation and custom ModelBinding... it may be worth looking at how much time it would actually take to just create the ViewModels.

If you find a better approach, feel free to let me know :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文