Asp.net 来自httpHandler的响应在客户端上随机缺少字符

Asp.net 来自httpHandler的响应在客户端上随机缺少字符,asp.net,iis,httpresponse,httphandler,Asp.net,Iis,Httpresponse,Httphandler,问题: 当浏览器接收到来自.NET站点的响应时,通常会随机丢失部分原始内容(以两个字符为单位) 详细信息: 我们有一个名为CssCombineHandler的定制httpHandler,它将多个CSS文件的内容组合到一个axd文件中 它在web.config中的指定方式如下: <httpHandlers> <add path="css.axd" verb="*" type="MyNamespace.CssCombineHandler, MyNamespace"/> &

问题:

当浏览器接收到来自.NET站点的响应时,通常会随机丢失部分原始内容(以两个字符为单位)

详细信息:

我们有一个名为CssCombineHandler的定制httpHandler,它将多个CSS文件的内容组合到一个axd文件中

它在web.config中的指定方式如下:

<httpHandlers>
  <add path="css.axd" verb="*" type="MyNamespace.CssCombineHandler, MyNamespace"/>
</httpHandlers>
并且
文件
参数中列出的所有文件都被合并到响应中

相关代码如下所示:

<httpHandlers>
  <add path="css.axd" verb="*" type="MyNamespace.CssCombineHandler, MyNamespace"/>
</httpHandlers>
context.Response.ClearHeaders()
context.Response.ContentType=“text/css”
context.Response.Cache.SetExpires(someDate)
context.Response.Cache.SetMaxAge(someOtherDate)
context.Response.Cache.SetCacheability(HttpCacheability.Public)
context.Response.Cache.VaryByParams(“文件”)=True
context.Response.BufferOutput=False'请参阅下面的注释
Dim responseBody作为新的StringBuilder()
'(在此循环浏览文件)
Append(File.ReadAllText(context.Server.MapPath(currentFileUri.AbsolutePath)))
'(结束循环)
context.Response.Write(responseBody.ToString())'这里有完整、正确的字符串!
但是,当您检查响应时(例如,在Firefox或Chrome dev tools Network选项卡中),它通常至少有一个位置删除了一行中的两个字符。效果是随机的,取决于它发生的地方,但举例来说,这个CSS在原始

可见性:可见!重要的;
…可能会改成

可见!重要的;
我在组合文件中见过这种情况0-3次,这取决于它的总大小。对组合文件内容的任何更改(即对组合文件之一的更改,或对组合文件列表的更改)都可能导致丢失的字符移动到其他位置

我尝试过的事情:

我没怎么接触过这样的东西,所以请原谅我的无知。这就是我到目前为止所尝试的

  • 设置
    Response.BufferOutput=True
    。这似乎一开始就解决了这个问题。我可以看到响应现在有一个自动生成的
    content-length
    头,不再有
    Transfer-Encoding:chunked
这适用于较小的响应,但如果组合的文件超过两个,则可能是响应太大,而某个(.NET?IIS?)正迫使其返回到分块模式,然后又会丢失字符。我不知道阈值,但例如15k响应将正确缓冲,而82k响应将不正确缓冲

  • 我想这可能是一个编码问题,因为有些css文件是UTF-8,有些是Windows-1252。我手动将它们全部更改为UTF-8,添加
context.Response.ContentEncoding=Encoding.UTF8
context.Response.Charset=“UTF-8”
改成

File.ReadAllText(context.Server.MapPath(currentFileUri.AbsolutePath),Encoding.UTF8)
…但这没什么区别。这实际上是有意义的,因为我认为
Response.Write()
中的字符串已经正确了,所以组合不同的文件似乎没有问题

  • 通过在IIS中禁用静态和动态压缩,确认gzip没有问题

  • 已尝试在IIS中将ASP
    响应缓冲限制设置为2147483647

  • 尝试手动设置内容长度标题,以查看它是否可能覆盖自动分块(根据我阅读的某些内容)。我不知道如何获得合适的大小,但即使这样测试,响应上也不会显示任何内容长度的标题

context.Response.AddHeader(“内容长度”,“500000”)
  • 尝试使用
    输出流
    而不是
    响应。Write()
Dim bytes As Byte()=System.Text.Encoding.UTF8.GetBytes(responseByte.ToString())
context.Response.OutputStream.Write(字节,0,字节,长度)
注意事项:

  • ASP.NET 4.0,Web窗体应用程序
  • IIS 10,应用程序池以经典模式运行
  • 此处理程序不调用
    Response.Flush()
  • 此处理程序不接触
    Response.Filter
  • 虽然我把这个问题描述为随机的,但它仍然足够一致,不会是一个奇怪的网络故障或其他什么。我可以在本地复制,也可以在我们的beta和prod服务器上复制。对于同一时刻的同一个组合文件,我可以在客户端上一致地复制给定的响应

事实证明,我们有一个单独的http模块,我们在其中设置了一个
响应。过滤器
来动态地将CSS文件中的URL替换为适合环境的正确值(例如,测试版与生产版URL)

显然,当你使用一个过滤器时,它会使用一个内部流或其他什么东西,我仍然不确定确切的原因,但将不同的流(当一个流的总内容太大时?)组合到响应的最终输出中时,出现了一些问题

我们通过避免在组合的css.axd文件上运行这个过滤器,而只在普通的css文件上运行它(以防直接命中任何css文件)来修复它。然后在cssCombineHandler中,我们在
response.write()前面的组合CSS字符串上运行相同的替换逻辑