1

View Models がすべて継承する BaseViewModel があります。

public class MagazineViewModel : BaseOutputViewMode
{
    public string TitleOfPublication { get; set; }
}

私のコントローラーでは、ファクトリ メソッドを使用して、入力に基づいて正しいビュー モデルを返します。

// e.g. viewModel contains an instance of MagazineViewModel 
BaseOutputViewModel viewModel = BaseOutputViewModel.GetOutputViewModel(output);

TryUpdateModel を使用して、「TitleOfPublication」キーが含まれていることがわかっている FormCollection にバインドしようとすると、ビュー モデルに設定されません。

if (!TryUpdateModel(viewModel, form))

これは、BaseOutputViewModel を使用して FormCollection キーをバインドする DefaultModelBinder と関係があると思います。「TitleOfPublication」は含まれていませんが、派生 MagazineViewModel には含まれています。

DefaultModelBinder の BindModel 動作をオーバーライドするために、独自のモデル バインダーを作成しようとしています。すべて正しく配線されており、TryUpdateModel 呼び出しの直後にデバッグできます。

 public class TestModelBinder : DefaultModelBinder, IFilteredModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Tried the following without success ....
        // 1. Quick hardcoded test
        // bindingContext.ModelType = typeof(MagazineViewModel);
        // 2. Set ModelMetadata, hardcoded test again
        // bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(MagazineViewModel));
        // 3. Replace the entire context
        // ModelBindingContext context2 = new ModelBindingContext();
        // context2.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(MagazineViewModel));
        // context2.ModelName = bindingContext.ModelName;
        // context2.ModelState = bindingContext.ModelState;            
        // context2.ValueProvider = bindingContext.ValueProvider;
        // bindingContext = context2;
    }
}

しかし、bindingContext の操作方法がわかりません。派生したビュー モデル プロパティを使用してバインドするように DefaultModelBinder に指示できるようにするには、何を更新する必要がありますか? それとも、私はこれを完全に誤解していますか!

MvcContrib の DerivedTypeModelBinder と同じように、CreateModel をオーバーライドしようとしましたが、バインダーに操作するモデルのインスタンスを与えているため、CreateModel が呼び出されることはありません。Mvc DLL で Reflector を使用すると、モデルが null の場合にのみ CreateModel を呼び出す "BindComplexModel" が存在します。

if (model == null)
{
    model = this.CreateModel(controllerContext, bindingContext, modelType);
}

どんなポインタでも大歓迎です!

乾杯

4

1 に答える 1

1

OK - ついにこの問題の根底にたどり着きました! 実際、私のモデル バインダーには何の問題もありませんでしたが、問題は最終的に名前/ID のないいくつかの入力タグにつながりました。

<input id="" name="" type="text">

肝心なのは、DefaultModelBinder でのこのテストでした。

// Simple model = int, string, etc.; determined by calling TypeConverter.CanConvertFrom(typeof(string))
// or by seeing if a value in the request exactly matches the name of the model we're binding.
// Complex type = everything else.
if (!performedFallback) {
     ValueProviderResult vpResult =
            bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (vpResult != null) {
                return BindSimpleModel(controllerContext, bindingContext, vpResult);
            }
        }

id/name がない場合、フォーム コレクションには "" のキーがあります。これは、GetValue がそのフィールドの値を正しく返し、単純なモデルとしてバインドし続けていることを意味します。

ID/名前が追加されると、フォーム コレクションには "" のキーが含まれません (TryUpdateModel を使用しているため、これがモデルの名前になりました)。これは、DefaultModelBinder が私のモデルを複合体として正しく処理し、派生型のプロパティを正常にバインドしたことを意味します。

乾杯

于 2010-11-01T12:32:56.723 に答える