Web API 操作参数间歇性为空

2023-12-26

相关问题:Web API ApiController PUT 和 POST 方法间歇性接收空参数 https://stackoverflow.com/questions/16091024/web-api-apicontroller-put-and-post-methods-receive-null-parameters-intermittentl

背景

在对现有 Web API 项目进行负载测试时,我注意到由于发布到操作时参数为空而导致出现许多空引用异常。

原因似乎是在开发环境中运行时注册了一个自定义消息处理程序来记录请求。删除此处理程序可以解决该问题。

据我所知,在 Web API 中我只能读取请求正文一次,并且读取它总是会导致我的参数为空,因为模型绑定无法发生。因此,我使用 ReadAsStringAsync() 方法和ContinueWith 来读取正文。看起来这在大约 0.2% 的请求中表现得很奇怪(在使用 Apache Bench 进行本地调试期间)。

Code

在最基本的层面上,我有以下几点:

Model

public class User
{
    public string Name { get; set; }
}

API控制器

public class UsersController : ApiController
{
    [HttpPost]
    public void Foo(User user)
    {
        if (user == null)
        {
            throw new NullReferenceException();
        }
    }
}

消息处理程序

public class TestMessageHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Content.ReadAsStringAsync().ContinueWith((task) =>
        {
            /* do stuff with task.Result */
        });

        return base.SendAsync(request, cancellationToken);
    }
}

...在应用程序启动期间注册

GlobalConfiguration.Configuration.MessageHandlers.Add(new TestMessageHandler());

我正在使用 WebAPI 4.0.30506.0,这是发布时的最新版本。该项目中的所有其他 MS 软件包也都运行最新版本(下面链接的演示项目现已更新以反映这一点)。

Testing

最初的测试是使用Loadster http://www.loadsterperformance.com/在带有 .NET 4.0.30319 的 Server 2008 R2 上针对负载平衡的 IIS 7.5 设置运行。我使用 Apache Bench 在带有 .NET 4.5.50709 的 Windows 7 上的 IIS 7.5 上本地复制此内容。

ab -n 500 -c 25 -p testdata.post -T "application/json" http://localhost/ModelBindingFail/api/users/foo

其中 testdata.post 包含

{ "Name":"James" }

通过此测试,我发现 500 个请求中大约有 1 个失败,所以约为 0.2%。

下一步...

我已经把我的演示项目放在GitHub https://github.com/jamesantrobus/WebAPI-ModelBindingError如果您想亲自尝试,除了我上面发布的内容之外,它是一个标准的空 Web API 项目。

也很乐意尝试任何建议或发布更多信息。谢谢!


我仍在调查其根本原因,但到目前为止,我的直觉是,ContinueWith() 正在不同的上下文中执行,或者在请求流已被处理的点或类似的情况下执行(一旦我发现我肯定会更新这一段)。

在修复方面,我很快就对三个可以无错误处理 500 个请求的进行了路测。

最简单的就是使用task.Result,但这确实存在一些问题(它可以显然会造成僵局 http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html,虽然YMMV)。

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    var result = request.Content.ReadAsStringAsync().Result;
    return base.SendAsync(request, cancellationToken);
}

接下来,您可以确保正确链接您的延续,以避免上下文出现任何歧义,但是它非常丑陋(而且我不能 100% 确定它是否没有副作用):

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    var result = request.Content.ReadAsStringAsync().ContinueWith(task =>
    {
        /* do stuff with task.Result */
    });

    return result.ContinueWith(t => base.SendAsync(request, cancellationToken)).Unwrap();
}

最后,最佳解决方案似乎是利用 async/await 来扫除任何螺纹污垢 https://stackoverflow.com/questions/15817594/should-i-use-continuewith-after-readasasync-in-delegatinghandler,显然,如果您停留在 .NET 4.0 上,这可能是一个问题。

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    var content = await request.Content.ReadAsStringAsync();
    Debug.WriteLine(content);
    return await base.SendAsync(request, cancellationToken);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Web API 操作参数间歇性为空 的相关文章

随机推荐

  • 定位具有动态 id 的元素的方法是什么?即使 Xpath 和 CSS 不起作用

    我正在使用一个动态网站 ID 可通过动态 GUI 获得 谁能解释一下如何编写手动 xpath 来查找网站中的元素
  • 如何将新的 json 字段添加到 groovy 中的现有 json

    我现有的 Json 看起来像 def json req date Tue 06 Oct 2015 09 10 52 GMT nonce 6cm7PmwDOKs devId
  • 如何让服务根据服务运行情况动态动作

    嗨 朋友们 我试图让我的服务动态运行 我已经为我的服务设置了大约 2 分钟的时间 如果假设它正在做大量的工作 意味着它将超过 2 分钟的时间限制 那么我们需要检查服务条件如果工作待处理意味着我们需要运行该实例直到完成 所以我在谷歌上尝试了下
  • 什么是 Mongoose 错误:对于路径“_id”处的值 XXX,转换为 ObjectId 失败?

    当发送请求至 customers 41224d776a326fb40f000001和一个文件 id 41224d776a326fb40f000001不存在 doc is null我正在返回一个404 Controller prototype
  • 单击闪亮应用程序中的网络节点后更新数据表

    我有一个简单的闪亮应用程序 它显示一个网络 在下表中您可以看到通过边和边的名称连接网络节点 我想更新数据表以在单击节点时仅显示选定的节点信息 例如 当我单击节点 articaine 时 表中将仅显示 articaine 连接 dataset
  • getenv 是否缓存结果?

    我有好几个电话要打给getenv在我的代码中 调用了很多次 所以我看到了优化的潜力 我的问题是 getenv以某种方式在内部缓存结果 或者它是否在每次调用时查询环境变量 我已经分析了代码 getenv不是瓶颈 但如果效率更高的话我还是想改变
  • 字典=哈希?

    字典基本上只是一个哈希表吗 还有福利 在 Ruby 代码 Hash new 0 中 末尾的 0 是做什么用的 表 字典和映射这三个词经常作为同义词使用 在数据结构的上下文中 哈希表 哈希映射是表 字典 映射的一种 The 0 是一个块 匿名
  • 如何在 UPS API 中指定货件是否为住宅货件?

    我在用着UPS api JSON 参考 ups com 开发工具包 1 我需要带有 住宅货运 的货运评级列表 2 我需要添加带有 居住地址 的货件 我是添加ResidentialAddressIndicator作为 1 英寸ShipTo地址
  • VBA Excel 类模块中的子属性

    我有一个名为 cTask 的模块 其中包含以下代码 Private pMile As String Public Property Get Mile As String Mile pMile End Property Public Prop
  • 通过电话号码获取当前时间

    我想编写一个 RoR 移动应用程序 它可以为我提供给定电话号码所在国家 地区的当前时间及其区号 有没有一个好的 api 可以做到这一点 这不是一个好主意 对于拥有多个不同时区和多个区号的国家 地区 您会采取什么措施 时区与区号不一定存在一对
  • 为什么实体不能具有具有一对一强制逆关系的唯一性约束?

    为什么实体不能具有具有一对一强制逆关系的唯一性约束 有两个实体 Person 属性 名称 关系 部门 一对一 非可选 部门 属性 标题 唯一约束 关系 人 对多 可选 模型无法在 iOS 9 XCode 7 0 1 中编译 并出现错误配置的
  • 端口自更新:“macPorts 来源:命令执行失败”

    我在尝试着selfupdate我的 Macports 但我收到以下消息 Error opt local bin port port selfupdate failed Error synchronizing MacPorts sources
  • Android意图街景不再工作

    我曾经从我的应用程序启动一个意图到地图来显示街景全景 自从几天以来 当我启动意图地图时 它说 此处不提供街景视图 我尝试运行一个新项目 其目的只是Google https developers google com maps documen
  • 如何获取类型的所有公共(获取和设置)字符串属性

    我正在尝试创建一个方法来遍历通用对象列表并替换它们的所有类型属性string这是null或空并更换 有什么好的方法可以做到这一点 我有这种 外壳 到目前为止 public static void ReplaceEmptyStrings
  • 停止 Django 将时间转换为 UTC

    时区让我发疯 每次我以为我已经弄清楚了 有人改变了时钟 我就会遇到十几个错误 我想我终于达到了存储正确值的地步 我的时代是timestamp with time zone在保存它们之前我不会删除时区 TIME ZONE Europe Lon
  • 我可以删除或移动文件夹 NuGetFallbackFolder 吗?

    我可以删除文件夹吗C Program Files dotnet sdk NuGetFallbackFolder 或者将其移动到其他文件夹 最好不要放在C盘 如果可以去除的话 怎么去除呢 直接删除文件夹吗 有任何副作用或损害吗 如果可以移动
  • 从未分配的内存中读取安全吗?

    从随机地址读取安全吗 我知道写作是未定义的行为 但是只阅读怎么样 嗯 在许多可视化调试器中 我可以看到任意地址的内存内容 这是怎么做到的 由于行为是不确定的 所以答案也是不确定的 或者至少是不稳定的 如果你幸运的话 随机地址是在内存范围内
  • 通过 Delphi 在网页上按下按钮 [重复]

    这个问题在这里已经有答案了 Ex1 WebBrowser OleObject Document GetElementByID ID HERE Click https stackoverflow com questions 10593494
  • 爪哇和谷歌地图

    是否可以在 Swing 或小程序中渲染谷歌地图 我知道我也可以使用美国宇航局世界风 http worldwind arc nasa gov 但对于一个简单的应用程序来说 这似乎太过分了 SwingX项目中有JXMapViewer组件 您可以
  • Web API 操作参数间歇性为空

    相关问题 Web API ApiController PUT 和 POST 方法间歇性接收空参数 https stackoverflow com questions 16091024 web api apicontroller put an