Best way to do partial update to ASP.NET MVC model ('merge' user submitted form with model)

后端 未结 1 1012
北荒
北荒 2020-12-22 06:14

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 th

相关标签:
1条回答
  • 2020-12-22 06:49

    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
    

    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
    
    0 讨论(0)
提交回复
热议问题