2014-12-03 26 views
3

在我們的MVC 2的應用程序之前,推進Request.InputStream我們有一個JSON模型綁定來實現,像這樣:達到ModelBinder的

public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     string input; 

     using (var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream)) 
     { 
      input = reader.ReadToEnd(); 
     } 

     return JsonConvert.DeserializeObject(
      input, 
      bindingContext.ModelType); 
    } 

更新到MVC 4後,我注意到,我們都拿到了進入的JSON職位空傳入車型。當挖掘它變得明顯的時候,上游正在推進這條河流。這很容易修復,像這樣

public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     string input; 

     //something upstream after MVC 4 upgrade is advancing the stream to end before we can read it 
     controllerContext.HttpContext.Request.InputStream.Position = 0; 

     using (var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream)) 
     { 
      input = reader.ReadToEnd(); 
     } 

     return JsonConvert.DeserializeObject(
      input, 
      bindingContext.ModelType); 
    } 

但我想知道發生了什麼事情,使更改必要?以前的實施只是巧合工作嗎?

+1

什麼是Request.Content的價值再次推進了Request.InputStream到流,我們需要結束重置Request.InputStream?這已經被填充了嗎?如果是這樣,這可能解釋爲什麼InputStream需要重新定位。 MVC4還添加了Restful WebAPI,它可以直接支持將請求正文解析爲模型參數。 – B2K 2015-02-19 15:47:05

回答

3

不,以前的實施並非巧合。

ASP.NET MVC 3介紹內置JSON綁定支持,它使操作方法能夠接收JSON編碼的數據並將其模型綁定到操作方法參數。

JsonValueProviderFactory默認註冊在ASP.NET MVC 3及之後。 JSON值提供程序在模型綁定之前運行並將請求數據序列化爲字典。字典數據然後被傳遞給model binder

讓我們來看看JsonValueProviderFactory works.Here是如何鏈接,在ASP.NET MVC開源代碼JsonValueProviderFactory.cs

GetDeserializedObject方法提供的JsonValueProviderFactory的源代碼,在JsonValueProviderFactory.cs定義,讀取stream如果Content-Type設置爲application/json因此它在流的末尾離開Request.InputStream。所以這裏首先調用GetDeserializedObject,然後調用BindModel。由於 GetDeserializedObject已經讀取流一次,在BindModel

private static object GetDeserializedObject(ControllerContext controllerContext) 
{ 
    if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) 
    { 
      // not JSON request 
      return null; 
    } 
    StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream); 
    string bodyText = reader.ReadToEnd(); 
    if (String.IsNullOrEmpty(bodyText)) 
    { 
     // no JSON data 
     return null; 
    } 
    JavaScriptSerializer serializer = new JavaScriptSerializer(); 
    object jsonData = serializer.DeserializeObject(bodyText); 
    return jsonData; 
} 
+0

謝謝,這很有道理。您引用的字典是否與@B2K的評論中引用的Request.Content相同? 我應該改變我的模型聯編程序實現與本詞典一起工作嗎? – AlexCuse 2015-02-23 15:37:19