gpt4 book ai didi

c# - 在到达 ModelBinder 之前推进 Request.InputStream

转载 作者:行者123 更新时间:2023-11-30 16:09:38 25 4
gpt4 key购买 nike

在我们的 MVC 2 应用程序中,我们有一个像这样实现的 JSON 模型绑定(bind)器:

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

但我想知道发生了什么使得必须进行更改?之前的实现只是巧合吗?

最佳答案

不,之前的实现并非巧合。

ASP.NET MVC 3 引入了内置 JSON 绑定(bind)支持,使操作方法能够接收 JSON 编码数据并将其模型绑定(bind)到操作方法参数。

JsonValueProviderFactory 默认在 ASP.NET MVC 3 及以后的版本中注册。 JSON 值提供程序在模型绑定(bind)之前运行并将请求数据序列化到字典中。然后将字典数据传递给 model binder

让我们看看 JsonValueProviderFactory 是如何工作的。这里是 ASP.NET MVC 开源代码 JsonValueProviderFactory.cs 中提供的 JsonValueProviderFactory 的源代码链接。

GetDeserializedObject 方法,在 JsonValueProviderFactory.cs 中定义,如果设置了 Content-Type,则读取 streamapplication/json ,因此它将 Request.InputStream 留在流的末尾。所以这里先调用GetDeserializedObject,再调用BindModel。自从GetDeserializedObject已经读取了一次流并将Request.InputStream推进到流的末尾,我们需要重新设置Request.InputStreamBindModel

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

关于c# - 在到达 ModelBinder 之前推进 Request.InputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27273122/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com