【发布时间】:2013-12-13 12:56:33
【问题描述】:
我正在尝试扩展我的 REST 服务(使用 WCF/webHttpBinding 构建),以便客户端可以上传压缩数据。我不确定实现这一点的最佳方法是什么,但我认为如果传入请求的 Content-Encoding 设置为 gzip,添加一个 HTTP 模块将解压缩数据会相当容易。
所以我创建了一个从 IHttpModule 派生的类,实现如下:
private void OnBeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication) sender;
var context = app.Context;
var contentEncoding = context.Request.Headers["Content-Encoding"];
if (contentEncoding == "gzip")
{
// some debug code:
var decompressedStream = new GZipStream(context.Request.InputStream, CompressionMode.Decompress);
var memoryStream = new MemoryStream();
decompressedStream.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(memoryStream);
string msg = streamReader.ReadToEnd();
context.Request.InputStream.Seek(0, SeekOrigin.Begin);
app.Request.Filter = //new TestFilterStream(app.Request.Filter);
new System.IO.Compression.GZipStream(
app.Request.Filter, CompressionMode.Decompress);
}
}
我看到的问题是 GZipStream 解压缩实际上从未执行过。我已经确认传入的数据实际上是 gzip 的(msg 变量包含正确的数据)。我还尝试在上面创建自己的流类 (TestFilterStream) 并将其分配给 app.Request.Filter,并且我已经确认 ASP.NET 实际上没有调用流类中的任何成员。所以看起来虽然可以指定一个过滤器,但实际上并没有使用该过滤器。
实际使用的不是HttpApplication.Request.Filter吗?
【问题讨论】:
-
您是否尝试过在没有其他调试代码的情况下设置
Request.Filter?可能是您已经读取了请求流,因此之后它将不再应用过滤器。 -
我相信没有理由相信 Request.InputStream 是可搜索的。可能不是。尝试删除您的调试代码,无论如何它可能是错误的(您可能必须在 decompressedStream 真正将任何内容写入内存流之前关闭/刷新它)。
-
请缩小问题范围,因为从您的问题中不清楚实际错误发生的位置和时间。问题实际上是
GZipStream没有读取底层流吗?contentEncoding是否等于"gzip",if块中的代码是否被调用?您是否尝试过在调用此方法时记录?你确定你的模块被加载了吗? -
为什么不使用 WCF 内置的功能?可以实现
IDispatchMessageInspector,解压BeforeSendReply函数中的内容。我认为您还需要将WebBodyFormatMessageProperty设置为Raw。
标签: c# asp.net wcf filter gzip