C# 在到达ModelBinder之前推进Request.InputStream
在我们的MVC 2应用程序中,我们实现了一个JSON模型绑定器,如下所示:C# 在到达ModelBinder之前推进Request.InputStream,c#,asp.net-mvc,asp.net-mvc-4,C#,Asp.net Mvc,Asp.net Mvc 4,在我们的MVC 2应用程序中,我们实现了一个JSON模型绑定器,如下所示: public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { string input; using (var reader = new StreamReader(controllerContext.HttpContext
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);
}
在更新到MVC4之后,我注意到我们得到了传入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);
}
但我想知道发生了什么使得改变成为必要?先前的实现是否只是巧合?否,先前的实现不是巧合
ASP.NET MVC 3
引入了内置的JSON绑定支持,使操作方法能够接收JSON编码的数据并将其模型绑定到操作方法参数
JsonValueProviderFactory
默认情况下在ASP.NET MVC 3及以后版本中注册。JSON
值提供程序在模型绑定之前运行,并将请求数据序列化到字典中。然后将字典数据传递到模型活页夹
让我们看看JsonValueProviderFactory
是如何工作的。下面是ASP.NET MVC开放源代码中提供的JsonValueProviderFactory
源代码的链接
JsonValueProviderFactory.cs
中定义的GetDeserializedObject
方法,如果内容类型设置为application/json
,则读取流
,从而将请求.InputStream
保留在流的末尾。因此这里首先调用GetDeserializedObject
,然后调用BindModel
。自从
GetDeserializedObject
已经读取了一次流,并提升了请求。InputStream
到流的末尾,我们需要重置请求。InputStream
再次进入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;
}
请求内容的价值是什么?已经有人住了吗?如果是这样,这可能解释了为什么需要重新定位InputStream。MVC4还添加了RESTfulWebAPI,它直接支持将请求主体解析为模型参数。您引用的词典是否与@B2K注释中引用的请求内容相同?我是否应该更改模型绑定器实现以使用此词典?