0

我的問題與this stack overflow question中的情況基本相同,我發現自己希望加載現有的有效版本的模型從數據庫中,並更新其中的一部分,因爲某些子字段的字段暴露在我的Web表單上。對ASP.NET MVC模型進行部分更新的最佳方式(用模型將用戶提交的表單'合併')

是否有無論如何我可以使模型綁定過程保證我的ID屬性將被首先綁定?

如果我可以保證這一件事,那麼,在ViewModel的ID屬性的setter中,我可以觸發一個'load',以便該對象最初從數據庫(或WCF服務..或Xml文件..或其他選擇存儲庫),然後從FORM表單提交的其餘屬性整齊地合併到對象中,因爲MVC完成了它的模型綁定過程。

然後,我IValidatableObject.Validate方法邏輯將很好地告訴我,如果得到的對象仍然是有效的..等等等等..

它只是在我看來,有寫管道在那裏我有模型的兩個實例(knownValidDomainModelInstanceFromStorage,postingPartialViewModelInstanceFromForm),然後手動映射到期望的屬性上是重複真正已經由MVC處理的東西...如果我只能控制身份的綁定順序。


編輯 - 我發現屬性綁定順序可以用自定義綁定器操縱。非常簡單地。閱讀下面發佈的答案。仍然歡迎您的反饋或意見。

回答

0

好吧,在閱讀了關於如何定製默認模型綁定器之後,我認爲這一小部分代碼可能會做一些排序屬性的技巧,並且每次都會給我所需的綁定順序。基本上允許我首先綁定標識屬性(從而允許我讓View Model觸發'加載'),從而允許模型綁定過程的其餘部分基本上以合併的方式運行!

''' <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過程中頂部的最常見的屬性名稱...

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

我已經開始使用這個概念,至今它似乎工作得很好。必須在我的ViewModel的ID設置工具上做一些工程,使其按照我想要的方式進行加載,而無需對其自身進行遞歸。但是,在此之後,這一切似乎都很簡單。沒有更多的部分模型或部分映射惡夢。希望其他人認爲它和我一樣有用。 – bkwdesign