2010-11-26 15 views
4

UpdateModelメソッドを実行時に取得されたサブクラスに使用すると、誰かが私がそれをトータルハッシュしているかどうか、 /または私がしようとしていることが可能かどうか。MVC UpdateModelとサブクラスvsベースクラス

私は、部分的なビューの束の検証を制御するために一般的なアクションを使用しています。私は、部分的な見方ごとに特定の行動をとることをやめようとしています。

各部分図には、ベースモデルから派生した独自のモデルを持っています

public class ModelA : ModelBase{ 
    [Required] 
    public string SomeStringProperty{get;set;} 
... 
} 
public class ModelB : ModelBase{ 
    [Required] 
    public DateTime? SomeDateProperty{get;set;} 
... 
} 
public class ModelBase{ 
    public Guid InstanceId{get;set;} 
} 

私が提出したフォーム要素とその値を取得するためにアクションにFormCollectionを使用しています、これはモデルのタイプを含みViewがリクエストを検証するために使用する必要があることを示します。 この例では、このによるセキュリティへの影響を無視し、私は彼らの意識だと、これは

[HttpPost] 
    public ActionResult ChangeCaseState(int id, FormCollection formCollection) 
    { 
     Guid instanceId = new Guid(formCollection["instanceId"]); 
     string modelType = formCollection["modelType"]; 
     //Return a specific Model class based on the event/modelType 
     var args = GetStateModelClass(modelType, instanceId); 

     try 
     { 
      UpdateModel(args); 
      if(Model.IsValid){ 
      ... 
     } 
     catch (Exception) 
     { 
      return View("~/Views/Shared/StateForms/" + modelType + ".ascx", args); 
     }... 

概念の内部だけで証明されており、ここで私はに基づいてサブクラスを返すために使用しているコードです。 modelTypeはコントローラに渡されます。

private static ModelBase StateModelClassFactory(string stateModelTypeName, Guid instanceId) 
     { 
      switch (stateModelTypeName) 
      { 
       case "modelTypeA": 
        return new ModelA(workflowInstanceId); 
       case "modelTypeB": 
        return new ModelB(workflowInstanceId); 
    ... 
    } 

StateModelClassFactoryメソッドの戻り値の型が、私は実際にサブクラスを返すてるにもかかわらず、基本クラスであるので、のUpdateModelメソッドが使用するモデルバインダーは基本クラス内の値に対してバインドします。

どのように私はこの問題を解決することができますか?

UPDATE:

public class CustomModelBinder : DefaultModelBinder 
    { 
     public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
      { 

そして、ボンネットの下に、もう少しで何が起こっていたか確認するために、正しい基本クラスに新しいモデルバインダーを割り当て:

私は、お客様のモデルバインダーを作成しました:

ModelBinders.Binders.Add(typeof(ModelBase), new CaseController.CustomModelBinder()); 

モデルバインダーをデバッグしてbindingContextを検査すると、Modelプロパティは正しいサブクラスですが、ModelTypeプロパティはベースクラスのプロパティです。 BindModelメソッド内でModelTypeを変更することを検討する必要がありますか?これを行う方法の指針があれば、ModelTypeのセッターは冗長化されているようです。私はまた、サブクラスのSomeDatePropertyがPropertyMetadataプロパティでactaullyであることに気付きました....私が望むように動作するように見えます。

答えて

2

私は私の問題を解決したと思います。基本的に、UpdateModelを呼び出す前にModelクラスを取得しているため、モデルがサブクラスのモデルであってもModelBinderがBaseClassをバインドしています - これは私の問題を解決するために使用したコードです:

public class SubClassModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var model = bindingContext.Model; 
     var metaDataType = ModelMetadataProviders.Current.GetMetadataForType(null, model.GetType()); 
     bindingContext.ModelMetadata = metaDataType; 
     bindingContext.ModelMetadata.Model = model; 

     return base.BindModel(controllerContext, bindingContext); 
    } 
} 

そして、Global.asaxの中:彼のinitalポインタのためのダーリンに

ModelBinders.Binders.Add(typeof(ModelBase), new SubClassModelBinder()); 

感謝。

[HttpPost] 
public ActionResult ChangeCaseState(int id, FormCollection formCollection) 
{ 
    ...try 
    { 
     UpdateModel((dynamic)args);//!!notice cast to dynamic here 
     if(Model.IsValid){ 
     ... 
    } 
    catch... 

これは私のタイプの利用可能なすべてのプロパティを設定するために表示されます。私は、この特定の問題に遭遇した、より良い一般的なアプローチだけでUpdateModelにそれを通過させながらdynamicにあなたのモデルをキャストすることであろうことがわかっ

+0

+1。あなたのソリューションを共有していただきありがとうございます。 –

0

この問題を解決するには、文字列プロパティの値に基づいて正しい子インスタンスが返される基本型のカスタムモデルバインダーを作成します。

+0

おかげダーリンは、私はあなたのソリューションへのスタートと思われるもので、迅速なプレイを持っていたし、質問を更新しました。 – Tr1stan

5

私の変数が基本型と比較されているかどうかは関係ありません。

この問題のためのCodePlexに提出された作業項目があります:http://aspnet.codeplex.com/workitem/8277?ProjectName=aspnet

+0

ありがとうございます。私は.net 3.5を使用していました(質問にタグが追加されました)。私はまだ動的ネットワーキングに取り組んでいません.net 4.0のウェブサイトではまだ作業していませんが、まだ問題がある場合はこれを試してみてください。 – Tr1stan

+0

いいえ、UpdateModelではなくTryUpdateModelを使用して動的にキャストすると、この同じ問題が発生しました。 – blins

+0

結婚してください!ありがとう、私はこの地獄に出くわす前に地獄にいた。 x – ctrlplusb

関連する問題