对 ASP.NET MVC 模型进行部分更新的最佳方法(“合并"用户提交的表单与模型) [英] Best way to do partial update to ASP.NET MVC model ('merge' user submitted form with model)

查看:44
本文介绍了对 ASP.NET MVC 模型进行部分更新的最佳方法(“合并"用户提交的表单与模型)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题与这个堆栈溢出问题中呈现的情况基本相同,其中我发现自己想要从数据库加载现有的有效模型版本,并在我的 Web 表单上公开某些字段子集时更新其中的一部分.

My question is basicially the same as the situation presented in this stack overflow question where I find myself wanting to load the existing valid version of model from the DB, and update a portion of it as a certain sub-set of fields are exposed on my web form.

无论如何我可以让模型绑定过程保证首先绑定我的 ID 属性吗?

Is there anyway I can make the Model Binding process guarantee that my ID property will be bound first?

如果我能保证这一点,那么,在我的 ViewModel 的 ID 属性的 setter 中,我可以触发加载",以便对象最初从 DB(或 WCF 服务..或 Xml 文件)填充.. 或其他选择的存储库),然后当 MVC 完成它的模型绑定过程时,从 FORM 提交的剩余属性整齐地合并到对象中.

If I could guarantee this one thing, then, inside the setter of my ViewModel's ID property, I could trigger a 'load', so that the object is initially populated from the DB (or WCF service.. or Xml file.. or other repository of choice) and then the remaining properties submitted from the FORM post neatly merge into the object as MVC finishes up it's model binding process.

然后,我的 IValidatableObject.Validate 方法逻辑会很好地告诉我结果对象是否仍然有效......等等......

Then, my IValidatableObject.Validate method logic will nicely tell me if the resulting object is still valid.. and so forth and so on..

在我看来,必须在我有两个模型实例(knownValidDomainModelInstanceFromStorage,postedPartialViewModelInstanceFromForm)的地方编写管道,然后手动映射所需的属性是重复一些已经由 MVC 真正处理的事情......如果我可以的话只控制身份的绑定顺序.

It just seems to me that having to write plumbing where I have two instances of a model(knownValidDomainModelInstanceFromStorage, postedPartialViewModelInstanceFromForm) and then manually mapping over desired properties is to repeat something that is really already handled by MVC... if I could only control the binding order of the identity.

编辑 - 我发现可以使用自定义绑定器操作属性绑定顺序.非常简单地.阅读我在下面发布的答案.仍然欢迎您的反馈或意见.

EDIT - I discovered property binding order CAN be manipulated with a custom binder. Very easily. Read the answer I posted below. Would still welcome your feedback or observations.

推荐答案

好的,在阅读了如何自定义默认模型绑定器之后,我认为这段代码可能只是对属性进行排序的技巧,并且会给我每次所需的绑定顺序.基本上允许我首先绑定身份属性(从而允许我让我的视图模型触发加载"),从而允许模型绑定过程的其余部分基本上作为合并运行!

Ok, after reading up on how to customize the default model binder, I think this bit of code just may do the trick of sorting the properties and will give me the desired binding order every time. Basically allowing me to bind the identity properties first (and thus allowing me to have my View Model trigger a 'load') allowing the remainder of the model binding process to function essentially as a merge!

''' <summary>
''' A derivative of the DefaultModelBinder that ensures that desired properties are put first in the binding order.
''' </summary>
''' <remarks>
''' When view models can reliably expect a bind of their key identity properties first, they can then be designed trigger a load action 
''' from their repository. This allows the remainder of the binding process to function as property merge.
''' </remarks>
Public Class BindIdFirstModelBinder
        Inherits DefaultModelBinder

    Private commonIdPropertyNames As String() = {"Id"}
    Private sortedPropertyCollection As ComponentModel.PropertyDescriptorCollection

    Public Sub New()
        MyBase.New()
    End Sub

    ''' <summary>
    ''' Use this constructor to declare specific properties to look for and move to top of binding order.
    ''' </summary>
    ''' <param name="propertyNames"></param>
    ''' <remarks></remarks>
    Public Sub New(propertyNames As String())
        MyBase.New()
        commonIdPropertyNames = propertyNames
    End Sub

    Protected Overrides Function GetModelProperties(controllerContext As ControllerContext, bindingContext As ModelBindingContext) As ComponentModel.PropertyDescriptorCollection
        Dim rawCollection = MyBase.GetModelProperties(controllerContext, bindingContext)

        Me.sortedPropertyCollection = rawCollection.Sort(commonIdPropertyNames)

        Return sortedPropertyCollection
    End Function

End Class

然后,我可以注册它来代替我的 DefaultModelBinder,并提供我希望浮动"到 ModelBinding 过程顶部的最常见的属性名称...

Then, I can register this in place of my DefaultModelBinder, and supply the most common property names that I'd like to have 'floated' to the top of the ModelBinding process...

    Sub Application_Start()

            RouteConfig.RegisterRoutes(RouteTable.Routes)
            BundleConfig.RegisterBundles(BundleTable.Bundles)
            ' etc... other standard config stuff omitted...
            ' override default model binder:
            ModelBinders.Binders.DefaultBinder = New BindIdFirstModelBinder({"Id", "WorkOrderId", "CustomerId"})
    End Sub

这篇关于对 ASP.NET MVC 模型进行部分更新的最佳方法(“合并"用户提交的表单与模型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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