博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
只在UnitTest和WebHost中的出现的关于LogicalCallContext的严重问题
阅读量:6423 次
发布时间:2019-06-23

本文共 4027 字,大约阅读时间需要 13 分钟。

最近一直在进行公司内部框架的升级工作,其中一个小的部分就是通过HttpSessionState和CallContext建立一套统一的、可扩展的用于管理上下文信息的框架。在为写好的程序编写Unit Test和QuickStart的时候,遇到了两个基于LogicalCallContext的严重问题。导致这两个问题的根源还没有来得及去追踪,或许是微软VS  Unit Test框架本身和WebHost本身的一个Bug。现在将其写出来,一来是希望读者在遇到相同情况的时候知道LogicalCallContext可能是影响因素之一,另一方面也希望借助社区的力量快速找到问题的症结。以下内容假定读者已经对CallContext有一个大概的了解,并且明白LogicalCallContext和IllogicalCallContext之间的区别。对此不了解的读者,可以参考我的文章《》。

一、在VS Unit Test下设置LogicalCallContext导致的序列化问题

为了演示在Unit Test下设置LogicalCallContext会导致怎样的问题,为此我写了一个非常简单的例子去重现它。首先我定义了如下一个形如Key-Value 的类型:LogicalContextItem<TValue>:

1: [Serializable]
2: public class LogicalContextItem
3: {
4:     public string Key { get; private set; }
5:     public TValue Value { get; set; }
6: 
7:     public LogicalContextItem(string key, TValue value)
8:     {
9:         if (string.IsNullOrEmpty(key))
10:         {
11:             throw new ArgumentNullException("key");
12:         }
13:         this.Key = key;
14:         this.Value = value;
15:     }
16: }

然后通过如下一个TestMethod测试一个以LogicalCallContext的形式保存的上下文(通过调用CallContext的静态方法LogicalSetData)是否可以通过相同的Key被正常获取。

1: [TestClass]
2: public class LogicalSetDataFixture
3: {
4:     [TestMethod]
5:     public void LogicaSetData()
6:     {
7:         LogicalContextItem
userName = new LogicalContextItem
("__userName", "Foo");
8:         CallContext.LogicalSetData(userName.Key, userName);
9:         Assert.AreEqual
("Foo", ((LogicalContextItem
)CallContext.LogicalGetData("__userName")).Value);
10:     }
11: }

但是运行上面的UnitTest的时候,在TestResult对话框中会出现一个Error。从下图中我们可以看出这是一个序列化的错误,具体的出错信息为:Unit Test Adapter threw exception: Type is not resolved for member 'UnitTests.LogicalContextItem`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]],UnitTests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null',即我们自定义的类型无法解析。这就有点让人费解了,在这个实例中,LogicalContextItem<TValue>:类型本身是直接定义在UnitTest这个项目之中的,何来无法解析之理。 

二、在VS ASP.NET WebHost下设置LogicalCallContext导致的序列化问题

我们知道,为了给基于ASP.NET的Web应用的开发者带来便利,Visual Studio内置了一个简单(和IIS比较而言)的Web应用承载工具,即WebHost。如果采用基于WebHost的承载方式(这是默认的承载方式),上面的错误同样会发生。为了演示,我们同样使用上面定义的LogicalContextItem<TValue>类型,然后在一个单纯的WebPage中的Load事件处理方法中编写了如下一段简单的代码:

1: public partial class _Default : System.Web.UI.Page
2: {
3:     protected void Page_Load(object sender, EventArgs e)
4:     {
5:         LogicalContextItem
userNameContext = new LogicalContextItem
("__userName", "Foo");
6:         CallContext.LogicalSetData(userNameContext.Key, userNameContext);
7:         var userName = ((LogicalContextItem
)CallContext.LogicalGetData("__userName")).Value;
8:         Response.Write(userName);
9:     }
10: }

直接运行上面的程序,SerializationException异常照常被抛出,从下图给出的错误对话框可以看出,该异常具有和上面完全一样的错误信息,即不能解析我们自定义的LogicalContextItem<TValue>类型。

为了找出抛出SerializationException异常的根源,我们可以来该异常的StatckTrace。从下面给出的内容,我们可以看出来该异常最终就是通过WebHost抛出来得。

1: at Microsoft.VisualStudio.WebHost.Host.ProcessRequest(Connection conn)
2: at Microsoft.VisualStudio.WebHost.Server.OnSocketAccept(Object acceptedSocket)
3: at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
4: at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
5: at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
6: at System.Threading.ThreadPoolWorkQueue.Dispatch()
7: at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

三、采用IIS承载我们的Web应用可以解决上述问题

为什么我说这个问题只和内置于VS中的Web应用承载工具WebHost有关呢?一来是因为上面给出的异常StackTrace已经明显反映了异常最后总就是从WebHost跑出来的。另一个主要的原因就是,如果我直接采用IIS来承载的话,运行上述的代码后一切正常。有兴趣的读者可以从下载实例程序进行试验。你只需要该Web应用进行了如下配置,放弃使用Vistual Studio Development Server,而选用Local IIS Web Server即可。

作者:蒋金楠
微信公众账号:大内老A
微博:
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号
蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
你可能感兴趣的文章
房地产英语 Real estate词汇
查看>>
python接口自动化测试(八)-unittest-生成测试报告
查看>>
第 26 章 MySQL
查看>>
C#中三种截屏方式总结
查看>>
Spring.net 学习笔记之ASP.NET底层架构
查看>>
C# System.Windows.Forms.WebBrowser中判断浏览器内核和版本
查看>>
Java 动态太极图 DynamicTaiChi (整理)
查看>>
微信公众平台后台编辑器上线图片缩放和封面图裁剪功能
查看>>
git使用教程2-更新github上代码
查看>>
张掖百公里,再次折戟
查看>>
SAP QM Batch to Batch的转移过账事务中的Vendor Batch
查看>>
本期最新 9 篇论文,帮你完美解决「读什么」的问题 | PaperDaily #19
查看>>
图解SSIS监视文件夹并自动导入数据
查看>>
Lucene.Net 2.3.1开发介绍 —— 四、搜索(一)
查看>>
MyBatis Review——开发Dao的方法
查看>>
技术研发国产化进程加快 看传感器企业如何展示十八般武艺
查看>>
技术助力第三次革命
查看>>
《HTML与CSS入门经典(第8版)》——2.6 总结
查看>>
新手指南:在 Ubuntu 和 Fedora 上安装软件包
查看>>
在 CentOS7.0 上搭建 Chroot 的 Bind DNS 服务器
查看>>