用于 DynamicObject 的 MVC3 ModelBinder

发布于 2024-10-19 16:15:31 字数 791 浏览 0 评论 0 原文

我正在寻找是否有示例项目、教程、contrib 分支或类似的内容,详细介绍了为 MVC3 实现自定义 ModelBinder 以支持从 DynamicObject 继承的对象。

我有一个域对象,它具有由数据库定义的动态数量的属性,并且这些属性可以在运行时更改。为了使使用该对象更容易,我使我的类实现继承自 DynamicObject,并通过 [dynamic] 关键字将模型传递给视图。

对象的所有动态属性都位于对象的称为“属性”的集合属性中。我想创建一系列编辑器模板来充实模型,理想情况下,我所要做的就是沿着 Html.EditorForModel() 进行调用,它将动态构建 UI。

问题是我没有太多运气找到能够检查 DynamicObject 并构建 UI 的 ModelBinder 实现(我认为这是正确的术语?)。

我在 Roberto Hernandez (@hernandezrobert) 在 MVC3 可扩展性(来源:http://mvcextensibility.codeplex。 com/),但我没有太多运气将其适应我的目的。我想知道是否有其他人尝试创建一个能够执行我所描述的操作的模型绑定器?或者也许可以为我指明正确的方向?

I'm looking to see if there is a sample project, tutorial, contrib branch or anything like that that details implementing a custom ModelBinder for MVC3 to support objects inheriting from DynamicObject.

I have an domain object that has a dynamic number of properties as defined by the database, and these can change at run time. To make using the object easier I've made my class implementation inherit from DynamicObject and am passing the model to the view via the [dynamic] keyword.

All of the dynamic properties for the object are in a collection property on the object called "Attributes". I'd like to create a series of editor templates to flesh out the model, ideally so all I have to do is make a call along the lines of Html.EditorForModel() and it will dynamically build the UI.

The problem is I'm not having much luck finding an implementation of a ModelBinder capable of inspecting a DynamicObject and scaffolding out the UI (I think that's the right term for this?).

I found the IDictionary ModelBinder project done in one of the MVCConf videos done by Roberto Hernandez (@hernandezrobert) on MVC3 Extensability (source at http://mvcextensibility.codeplex.com/) but I haven't had much luck adapting it to my purposes. I was wondering if anyone else has tried to create a model binder capable of doing what I'm describing? or could maybe point me in the right direction?

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

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

发布评论

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

评论(2

坐在坟头思考人生 2024-10-26 16:15:31

ModelBinder 不帮助生成视图,它们帮助将来自各种 Web 源(表单、查询字符串等)的原始参数映射到操作方法所需的输入参数(具体来说,如果您的输入参数是某些类型的类)排序而不是基元)。

您正在寻找的是如何生成视图模板的示例,我还没有见过动态视图模板。到目前为止,我见过的常规视图模板生成的最佳资源是 布拉德·威尔逊的博客。如果您有一种方法(听起来像您所做的)来弄清楚对象必须显示哪些属性以及有关如何显示它们的元数据(例如文本区域与输入类型=文本等),那么您应该能够跟着布拉德一起走。

ModelBinders don't help generate the view, they help map the raw parameters from various web sources (form, querystring, etc) to the input parameters expected by your action method (specifically, if your input param(s) are a class of some sort rather than primitives).

What you're looking for is an example of how to generate the view templates, which I've not seen for dynamics. The best resource for regular view template generation so far that I've seen is Brad Wilson's blog. If you have a means (which it sounds like you do) of figuring out what properties the object has to display along w/ metadata about how to display them (e.g. textarea vs. input type=text, etc), then you should be able to just follow along w/ Brad.

奢华的一滴泪 2024-10-26 16:15:31

我能够通过设置一个普通类作为我的 DanamicObject 的模型来解决我的情况,并像这样存储我的属性,因此

IList<DynamicProperty> DynamicProperties { get; set; }

我为 DynamicObject 创建了一个自定义视图,在该视图中我调用了其中一个助手来显示 DynamicProperties 属性。这使得 MVC 可以迭代集合并呈现每个属性。接下来,我有一个 DynamicProperty 视图,用于根据需要呈现属性。关键是您还必须呈现一个包含该特定属性的主键的隐藏字段。 MVC3 中的 ModelBinder 在这里比 MVc2 中做得更好,因此它会将数组索引呈现为字段名称的一部分,以便每个属性的主键和值在提交时正确配对。您可能想要专门为提交的数据创建一个 ViewModel,当我尝试使用详细信息/编辑视图中使用的相同模型类时遇到问题,因为我只渲染了字段的子集,因此当我绑定到时它们丢失了回发时相同的模型类。

您可以按照通常的方式处理保存,但对于此类对象,有一些安全方面的注意事项。由于属性的数量是动态的,因此无法确保提交的字段数量与最初呈现的字段数量相同。用户可以注入自己的属性,或者更糟糕的是添加您可能已明确排除的属性的字段。 AntiForgeryToken 可以防止此类提交发生在您的域之外,但随着 jQuery 等库提供的 DOM 操作的简便性和流行性,跨站点回发并不是唯一的问题,我不知道 AntiForgeryToken 是否会解决这个问题但我对此表示怀疑。

事实证明,这种方法比尝试从 DynamicObject 继承、实现 GetDynamicMemberNames 以及创建自定义 ModelBinder 以使用环绕它更容易。

不过,我确实创建了一个自定义 ModelMetaData 和验证提供程序来处理这些方面,因为这些属性不是强类型的,因此 MVC 没有任何注释可供使用。

I was able to solve my situation by setting up a normal class to serve as the Model for my DanamicObject, and having my properties be stored like so

IList<DynamicProperty> DynamicProperties { get; set; }

I created a custom view for the DynamicObject, and in that view I called one of the helpers to display the DynamicProperties property. This lets MVC iterate through the collection and render each property. Next I have a view for the DynamicProperty that I use to render the property as needed. The key is you also have to render a hidden field containing the primary key of that specific attribute. The ModelBinder in MVC3 does a much better job here than it did in MVc2, so it will render the array index as part of the field's name so that the primary key and value of each property get paired up correctly on the submit. You'll likely want to create a ViewModel specifically for the submitted data, I had issues when I tried to use the same model class used in the details/edit views because I only rendered a subset of fields so they were missing when I bound to the same Model class on postback.

You can handle the save however you would normally but there are a few considerations securitywise for this type of object. Because the number of attributes is dynamic, there is no way to ensure that the same number of fields are submitted as were originally rendered. The user could inject their own, or worse add in fields for a property you may have explicitly excluded. The AntiForgeryToken would prevent these sort of submissions from happened outside of your domain but with the ease and popularity of DOM manipulation provided by libraries like jQuery, cross site postbacks isn't the only concerns and I don't know if the AntiForgeryToken will account for this but I doubt it.

This approach proved to be easier than trying to inherit from DynamicObject, implement GetDynamicMemberNames, and making a custom ModelBinder to use wrap around it.

I did however create a custom ModelMetaData and Validation Provider to handle those aspects, since the properties are not strongly typed, so MVC didn't have any annotations to use.

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