2016-03-23 14 views
3

モデルバインダーのオーバーライドを書きました。MVC 5モデルバインダーオーバーライド

public override object BindModel(Controller context, ModelBindingContext bindingContext) 
{ 
    var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

    object returnVal = null; 

    if (value == null) 
     returnVal = base.BindModel(controllerContext, bindingContext); 
    else 
    { 
     /* custom logic here that never seems to get called. 
      returnVal = something(); 
     */ 
    } 

    return returnVal; 
} 

また、私のコントローラの1つにAJAX要求を行うjavascriptサービス(Angular)もあります。

AJAX要求は、intのコレクションをポストしようとします。私はモデルのバインダーをステップしてみました。valueは常にnullです。そしていくつかの魔法によって、base.BindModel()は私のコレクションを正しいC#オブジェクトにバインドすることができます。

この問題は、elseブロックが呼び出されないため、カスタムバインダーを使用できないという問題があります。 ValueProviderを使用する以外にも値を取得できる別の方法はありますか?

私はこのカスタムバインダーが正しく動作する前に(間違っているかもしれないメモリから)信じています。私は最近4.5から5.2に更新しました。この動作を変更した可能性のある更新されたものはありますか?

答えて

3

また、私のコントローラの1つにAJAX要求を行うjavascriptサービス(Angular)もあります。

...

これに伴う問題は、他のブロックが呼び出されることはありませんように私は私のカスタムバインダーを使用することができないということです。

  • 私はあなたのバインダーは、グローバルにも、パラメータのうちの1つまたは複数のアクション自体に正しく登録されていることを前提とするつもりです。
  • また、バインダーは予期したときに呼び出されていると仮定します。

バインドしようとしているモデル名に基づいてデータを見つけることができないため、nullです。この名前で値を見つけることができるかどうかは、モデル名と、クライアント要求で送信され、整列/一致する必要があるデータによって異なります。しかし、誰にでも、(モデルと配列を含む)一致するデータがクライアントから次の3つの理由で送信されない理由を教えてください:

  1. URLを使用する場合は、同じプロパティ名をクエリ文字列。例:?myArray=1&myArray=2&myArray=3。つまり、モデルバインダーではこれを考慮する必要があります。
  2. POSTでdata(本文)を使用している場合は、実際の配列オブジェクトである可能性があります。JSONでの例:{"myArray":[1,2,3,4]}
  3. ます。また、フォーム全体をシリアライズし、角度でそれを上に送信される可能性があります(あなたがより良いMVCでバインディング機能を使用することができるようになる

だから、より良いあなたの質問に答えるためにあなたは、これはあなたの角度工場、サービス、またはコントローラである可能性があり(データの形式は、ブラウザから送信され、どのようにそのが送信されて(クエリ文字列やデータペイロード内)されている

  1. を提供する必要があります )
  2. あなたがそう

への総集編にバインドしようとしているモデルの定義:bindingContext.ModelNameが期待される名前であり、あなたのモデルバインダーを見つけようとしているデータと一致する必要があります。 {"myArray":[1,2,3,4]}を送信していて、モデルプロパティの名前がProductIdsの場合は、常にnullになります。

私は最近、私が知っていないこと、ありません

を5.2.somethingに4.5から更新。


最終的な考え。また、デフォルトのモデルバインダーを実行させて、型が一致する場合は戻り値で何かを実行することもできます。バインドが問題なく行われたにもかかわらず、後処理をしたい場合、これがより良い選択になります。例:

public override object BindModel(Controller context, ModelBindingContext bindingContext) 
{ 
    var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

    object returnVal = base.BindModel(controllerContext, bindingContext); 

    /* check returnVal and then additional custom logic here */. 

    return returnVal; 
} 
-1

あなたはこのような何かを行っていることを確認してください: -

  1. カスタムモデルバインディング: -

    public class HomeCustomDataBinder : DefaultModelBinder 
    { 
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
        { 
         if (bindingContext.ModelType == typeof(HomePageModels)) 
         { 
          HttpRequestBase request = controllerContext.HttpContext.Request; 
    
          string title = request.Form.Get("Title"); 
          string day = request.Form.Get("Day"); 
          string month = request.Form.Get("Month"); 
          string year = request.Form.Get("Year"); 
    
          return new HomePageModels 
          { 
           Title = title, 
           Date = day + "/" + month + "/" + year 
          }; 
    
          //// call the default model binder this new binding context 
          //return base.BindModel(controllerContext, newBindingContext); 
         } 
         else 
         { 
          return base.BindModel(controllerContext, bindingContext); 
         } 
        } 
    
    } 
    
  2. 我々はカスタムクラスをコーディング完了したらApplication_Start()の下で私がGlobal.asaxで行うクラスを登録する必要があります。

    protected void Application_Start() 
    { 
        AreaRegistration.RegisterAllAreas(); 
        WebApiConfig.Register(GlobalConfiguration.Configuration); 
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
        RouteConfig.RegisterRoutes(RouteTable.Routes); 
        BundleConfig.RegisterBundles(BundleTable.Bundles); 
        AuthConfig.RegisterAuth(); 
        ModelBinders.Binders.Add(typeof(HomePageModels), new HomeCustomBinder()); 
    } 
    

    3)最後に、使用したいバインディングをコントローラに通知する必要があります。これは、私たちは以下のような属性[ModelBinder(typeof(HomeCustomBinder))]を使用して指定することができます。

    [HttpPost] 
    public ActionResult Index([ModelBinder(typeof(HomeCustomBinder))] HomePageModels home) 
    { 
        if (ModelState.IsValid) 
        { 
         ViewBag.Title = home.Title; 
         ViewBag.Date = home.Date; 
        } 
        return View(); 
    }