除了从异常堆栈中找到最早的异常代码处,这里还说一个小技巧,使用 ndspy 的 异常断点功能,在异常设置面板 定位 InvalidOperationException 异常即可。
接下来就可以让程序跑起来,当异常抛出时会自动断下来。
仔细看一下图中的文字标注,还是很好理解的,接下来继续追一下: response.ContentType = contentType2; 内部都做了什么。
public override string ContentType { get { return this.Headers[HeaderNames.ContentType]; } set { if (string.IsNullOrEmpty(value)) { this.HttpResponseFeature.Headers.Remove(HeaderNames.ContentType); return; } this.HttpResponseFeature.Headers[HeaderNames.ContentType] = value; } }可以看到 内部是给 this.HttpResponseFeature.Headers 赋值的,继续往下追:
从图中可以看到,最后的 HttpHeader._isReadOnly =true 导致异常的发生,罪魁祸首哈,接下来研究下这句 HttpHeader._isReadOnly=true 是何时被赋值的。
2. _isReadOnly=true 何时发生这个问题就简单多了,必定是 Response.WriteAsync("hello world!"); 造成了 _isReadOnly=true ,在 HttpHeader 下有一个 SetReadOnly 方法用于对 _isReadOnly 字段的封装,代码如下:
internal abstract class HttpHeaders { public void SetReadOnly() { this._isReadOnly = true; } }接下来在该方法处下一个断点,继续调试,如下图:
从图中可看到,原来 Response.WriteAsync("hello world!") 是可以封锁 HttpHeaders的,后续任何再对 HttpHeader 的操作都是无效的。。。
其实大家也可以想一想,不同的response,肯定会有不同的 header,要想叠加的话这辈子都不可能的,只能让后面的报错,如下:
1. response: HTTP/1.1 200 OK Date: Mon, 19 Oct 2020 14:37:54 GMT Server: Kestrel Transfer-Encoding: chunked c hello world! 2. view: HTTP/1.1 200 OK Date: Mon, 19 Oct 2020 14:39:01 GMT Content-Type: text/html; charset=utf-8 Server: Kestrel Content-Length: 2239 四: 总结这篇就是对群聊天过程中抛出问题的个人探究,一家之言,不过挺有意思,大家也可以多用用调试工具寻找问题,证明问题,纸上得来终觉浅,绝知此事要躬行,好了,希望本篇对您有帮助!