2016-03-23 83 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; 
} 

我也有一個javascript服務(在Angular中),它向我的一個控制器發出AJAX請求。

AJAX請求嘗試發佈整數集。我嘗試通過模型聯編程序,似乎value始終爲空。通過一些魔術,base.BindModel()仍然能夠將我的集合綁定到正確的C#對象。

與此問題是,我不能使用我的自定義聯編程序,因爲else塊永遠不會被調用。除了使用ValueProvider之外,還有其他方法可以獲得價值嗎?

我也相信,在這個自定義聯編程序工作正常(從內存可能是錯誤的)。我最近從4.5更新到5.2。有沒有更新過的內容可以改變這種行爲?

回答

3

我也有一個javascript服務(在Angular中)向我的控制器發出AJAX請求。

...

的問題,這是我不能用我的定製綁定的其他塊永遠不會被調用。

  • 我會假設你已經正確註冊粘結劑全局的或是動作本身上的一個或多個參數。
  • 我還會假設你的綁定器在你期望的時候被調用。

它爲空,因爲它無法根據您試圖綁定到的模型名稱找到數據。是否可以通過此名稱找到值取決於型號名稱和客戶端請求中發送的必須對齊/匹配的數據。但在此之前任何人都可以告訴你,爲什麼它不匹配的數據(包括與陣列模型),可以從客戶端三種方式之一發送:使用URL,你會重新使用在同一屬性名

  1. 如果請求參數。例如:?myArray=1&myArray=2&myArray=3。這意味着在你的模型聯編程序中,你將不得不考慮這一點。
  2. 如果在POST中使用data(body),那麼它可能是一個實際的數組對象。例如,在JSON:{"myArray":[1,2,3,4]}
  3. 你也可能被序列化整個表格,連同角發送過來(這將讓你更好地在MVC使用綁定功能)

因此,爲了更好地回答你的問題你將需要提供

  1. 數據的格式被從瀏覽器發送,以及如何其發送(查詢字符串或數據載荷)(這大概是你角工廠,服務,或控制器
  2. 你正在試圖綁定到

所以總括的模型定義:bindingContext.ModelName是預期的名稱,並且必須是你的模型粘合劑試圖找到數據相匹配。如果您發送的是{"myArray":[1,2,3,4]},但您的模型屬性名爲ProductIds,那麼它將始終爲空。

我最近從4.5更新到5.2.something

不,不,我知道的。


最後的想法。你也可以讓默認模型聯編程序執行,然後如果類型匹配,則使用返回值執行一些操作。如果綁定現在沒有問題發生,但你想做一些後處理,這將是一個更好的選擇。例如:

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(); 
    }