0

私の質問は基本的に、このスタック オーバーフローの質問で示されている状況と同じです。DBからモデルの既存の有効なバージョンをロードし、特定のフィールドのサブセットが公開されているときにその一部を更新したいと考えています。ウェブフォーム。

とにかく、ID プロパティが最初にバインドされることをモデル バインド プロセスで保証することはできますか?

この 1 つのことを保証できれば、ViewModel の ID プロパティのセッター内で「ロード」をトリガーして、オブジェクトが最初に DB (または WCF サービス.. または Xml ファイル.. またはその他) から読み込まれるようにすることができます。 MVC がモデル バインディング プロセスを完了すると、FORM ポストから送信された残りのプロパティがオブジェクトにきちんとマージされます。

次に、私の IValidatableObject.Validate メソッド ロジックは、結果のオブジェクトがまだ有効かどうかを適切に教えてくれます..などなど..

モデルの2つのインスタンス(knownValidDomainModelInstanceFromStorage、postedPartialViewModelInstanceFromForm)がある場所で配管​​を記述し、必要なプロパティを手動でマッピングする必要があるのは、MVCによって実際にすでに処理されていることを繰り返すことだと私には思えます... ID の拘束順序。


編集 - カスタムバインダーでプロパティバインディングの順序を操作できることを発見しました。とても簡単に。以下に投稿した回答を読んでください。ご意見やご感想をお待ちしております。

4

1 に答える 1

0

既定のモデル バインダーをカスタマイズする方法を読んだ後、このコードはプロパティの並べ替えのトリックを実行し、毎回目的のバインド順序を提供する可能性があると思います。基本的に、ID プロパティを最初にバインドできるようにする (したがって、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
于 2013-10-10T13:27:22.540 に答える