我开发了一个 IIS 7 HttpModule。我的目标是检查特定标签的响应内容。如果找到标签,则记录一些内容。
为了实现我的目标,我开发了一个定制的 ASP NET 响应过滤器。此过滤器扩展了 .NET Stream 类。
过滤器在 OnPreRequestHandlerExecute(Object source, EventArgs e) 事件上注册。
HTTP 模块已正确注册。过滤器正在工作。问题是,当我刷新页面时,Write the Write(byte[] buffer, int offset, int count) 方法被按预期调用,但是,解码它们时字节的内容是 gobbledygook。
这让我很困惑,为什么第一次响应字节被正确解码,但是在第二次请求(即页面刷新)之后它们却没有。下面是设置过滤器的代码和过滤器的 writer 方法的代码。任何帮助将不胜感激,因为我已经花了 3 天,调试,在谷歌上研究,但仍然没有快乐。
public void OnPreRequestHandlerExecute(Object source, EventArgs e)
{
HttpResponse response = HttpContext.Current.Response;
if (response.ContentType == "text/html")
{
response.ContentEncoding = Encoding.UTF8; //forcing encoding UTF8
response.Charset = "charset=utf-8";
Encoding encoding = response.ContentEncoding;
string encodingName = encoding.EncodingName;
response.Filter = new MyFilter(response.Filter, response.ContentEncoding);
}
}
public override void Write(byte[] buffer, int offset, int count)
{
string strBuffer = string.Empty;
try
{
strBuffer = Encoding.UTF8.GetString(buffer);
}
catch (EncoderFallbackException ex)
{
log(ex.Message);
}
// buffer doesn't contain the HTML end tag so we keep storing the
//incoming chunck of data
if (!strBuffer.Contains("</html>"))
{
log(strBuffer.ToString() );
_responseHtml.Append(strBuffer);
}
//the strbuffer contains the HTLM end tag ; we wrap it up now
else
{
_responseHtml.Append(strBuffer); //append last chunck of data
string finalHtml = _responseHtml.ToString();
byte[] bytesBuffer = Encoding.UTF8.GetBytes(finalHtml);
outputStream.Write(bytesBuffer, 0, bytesBuffer.Length);
}
}
}
这就是我得到的,在解码响应字节后,第二次调用 html 页面(即在浏览器上刷新)
?\b\0\0\0\0\0\0?yw??/????Og??V.\ak?t:JhY??xP,u?I?Y? \"?\0???w?|?W???\0R?M?Y??I7E{?]??_}???z??8K??!?5O?8???? ??k?^?~k\?u????f?lE??????s=i??gqY%??O????<9x???BKuZg?a???4? Fq???KJ?t??8??????????$e\?E?,?
更新。
第一个计时器,所以我不确定如何更新它。所以我把我所做的事情缩小/解决问题。
首先,还是No Joy。:-(
这就是我所做的:
- 由于 ASP NET 可以多次调用 Write 方法,因此我将字节存储在一个集合中,并将它们添加到集合中,每次 ASP NET 调用 Write 方法时
p
ublic override void Write(byte[] buffer, int offset, int count)
{
for (int i = 0; i < count; i++)
{
bytesList.Add(buffer[i]);
}
log("Write was called "+ "number of bytes: "+ bytesList.Count + " - " + count);
}
在 flush 方法上,我调用了一个对收集的所有字节执行一些工作的方法:
公共覆盖 void Flush() { byte[] bytesContent = ProcessResponseContent(bytesList); outputStream.Write(bytesContent, 0, bytesContent.Length); outputStream.Flush(); }
公共覆盖无效写入(字节[]缓冲区,整数偏移量,整数计数){
for (int i = 0; i < count; i++) { bytesList.Add(buffer[i]); } log("Write was called " + "number of bytes: " + bytesList.Count + " -" + count); }
私有字节[] ProcessResponseContent(List bytesList) {
byte[] bytesArray = bytesList.ToArray(); string html = string.Empty; byte[] encodedBytes = null; try { FilterEncoder encoder = new FilterEncoder(); html = encoder.DecodeBytes(bytesArray.Length, bytesArray); encodedBytes = encoder.EncodeString(html); log("after encoding - encodedBytes" + encodedBytes.Length); log("after encoding - bytesArray" + bytesArray.Length); } catch (Exception ex) { log("exception ocurred " + ex.Message);
...... ......
}
ProcessResponseContent 是一个愚蠢的方法。它只是将字节列表转换为字节数组;这个字节数组被解码成一个字符串。现在我们应该没有任何问题,因为我们在 bytesList (List ) 中获得了响应中发送的所有字节
字节数组原封不动地返回,因为代码的目的是将解码后的字符串登录到文件中。
log("after decoding " + html);
当我创建一个 UTF8Encoding 时,我遇到了一个异常。异常被记录到文件中。
第一次检索 html 页面时,内容会记录到文件中。
当我刷新页面(Ctrl + F5)时,会记录一个异常:
“发生异常无法将索引 0 处的字节 [8B] 从指定代码页转换为 Unicode”
请记住,我的 html 页面内容非常小。所有响应内容都在一个块上处理。
第一次访问页面时收到的字节数是 2805。就在这些字节被解码为字符串之前。
第二次调用页面 (Ctrl + F5) 接收到的字节数在解码之前是 1436。
为什么响应的字节数较少,我不确定。这可能会影响解码操作吗?
我希望这一切都有意义,如果有不清楚的地方,请告诉我。我一直在寻找这段代码很长时间。
谢谢,