2015-04-17 157 views
0

我想了解自定義綁定應該如何工作。使用DefaultModelBinder自定義模型綁定

假設

[HttpPost] 
public ActionResult MyAction(CustomType parameter) { 
    // do something 
} 

一個簡單的動作......和下​​面的表單數據

{ 
    parameter : "mydata" 
    parameter.Property1 : "something" 
    parameter.Property2 : 3 
} 

...及以下,非常簡單的定製綁定

public class MyBinder : DefaultModelBinder { 

     public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { 

      if (bindingContext.ModelType.Equals(typeof(CustomType))) { 
       string parameter = controllerContext.HttpContext.Request.Form[bindingContext.ModelName]; 
       object model = controllerContext.HttpContext.Cache[parameter]; 

       return model; 
      } 

      return base.BindModel(controllerContext, bindingContext); 

     } 

     protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) { 
      // not called 
      return base.CreateModel(controllerContext, bindingContext, modelType); 
     } 

     protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor) { 
      // not called 
      base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 
     } 

    } 

我可以看到BindModel方法被調用。但是,一旦我返回自定義對象,BindProperty方法永遠不會被調用Property1Property2。這很有道理,因爲我不打電話給base.BindModel()

所以我的問題是:如何應該BindModel被實現,它創造CustomType還呼籲在超類BindModel

+0

是什麼讓你覺得你需要一個自定義的模型綁定器。您發佈的數據與您的模型沒有任何關係。事實上,你有'參數:「mydata」'意味着模型綁定過程中發生的第一件事是'CustomType'類型的新實例被初始化,然後它試圖設置'CustomType =「mydata」的值當然會失敗(你不能將一個複雜的對象設置爲一個字符串)。發佈的數據需要是'{Property1:'something,Property2:3}',DefaultModelBinder會初始化一個新的CustomType並設置Property1和Property2的值。 –

+0

@StephenMuecke是的,你是對的,我爲這個人爲的例子道歉。請考慮一個場景,其中'parameter:「mydata」'包含與創建對象有關的有用數據,例如持有exise對象的字典的鍵或對象的串行表示。然後我想通過默認綁定器提供的遞歸屬性綁定來跟蹤這個對象檢索。我希望這個問題更清楚。 –

回答

0

我沒有這樣做了一段時間,但IIRC,你可以構建新的CustomType與屬性設置,而不是return new CustomType();

喜歡的東西:

+0

我寧願讓DefaultModelBinder處理屬性綁定而不是硬編碼每個表單鍵 –

0

我已對源代碼爲DefaultModelBinder,並發現內部方法BindComplexElementalModel。使用此自定義數據聯編程序可以實現所需的模型聯編行爲。

public class MyBinder : DefaultModelBinder { 

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { 

     if (bindingContext.ModelType.Equals(typeof(CustomType))) { 
      // get an instance of the model using the model prefix 
      string parameter = controllerContext.HttpContext.Request.Form[bindingContext.ModelName]; 
      object model = controllerContext.HttpContext.Cache[parameter]; 

      // populate the remaining model properties using reflection (yuck) 
      MethodInfo bindComplexElementalModel = 
       base.GetType().GetMethod("BindComplexElementalModel", BindingFlags.NonPublic | BindingFlags.Instance); 

      bindComplexElementalModel.Invoke(this, new object[] { controllerContext, bindingContext, model }); 

      return model; 
     } 

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

當然,使用一個內部框架,方法是不是一個乾淨的解決方案,所以我離開了這個問題,希望有人能提供一個更好的答案開放。

+0

你可以在新的自定義綁定中實現IModelBinder嗎? – MattDuFeu

+0

我確實想知道這是否是必需的。很多[一些資源](http://odetocode.com/blogs/scott/archive/2009/04/27/6-tips-for-asp-net-mvc-model-binding.aspx)建議繼承'DefaultModelBinder 「大概是因爲;如果要保持默認綁定程序提供的相同級別的靈活性(即所有對象屬性的自動和遞歸綁定),那麼編寫自己的自定義'IModelBinder'會涉及重寫很多默認功能? –

+0

[此問題]中的評論(http:// stackoverflow。com/questions/8535802/when-to-use-imodelbinder-versus-defaultmodelbinder)同意。我不知道答案,但至少你有它的工作。 – MattDuFeu

相關問題