在开发Web服务时,客户端与服务器之间的数据传输成本逐渐成为一个问题,这不仅影响响应速度,还增加了网络负载。本文介绍一种在服务器端压缩SOAP信封体,客户端解压缩的方法,通过SOAP过滤器实现,无需更改任何代码,也无需额外开销。
在编写此类应用程序时,有一些常见的建议需要遵循,其中包括但不限于以下几点:
尽管如此,有时确实需要通过Web传输大量数据,例如包含数千行数据的DataSet。这就是代码发挥作用的地方。
代码是一个DLL,需要在客户端和服务器两个项目中引用,包含3个简单的类:
必须重写ProcessMessage方法来通过SOAP机制的管道改变信封的主体。首先,验证过滤器是否启用,消息是否足够大以进行压缩。然后,创建一个自定义头部,通知客户端该消息应该被解压缩。接下来,创建信封主体元素的压缩流。最后,用新的压缩对象替换主体。
public override void ProcessMessage(SoapEnvelope envelope)
{
if (!m_bEnabled)
return;
XmlElement soapHeader = envelope.CreateHeader();
if (envelope.Body.InnerText.Length < (m_MinFilterSize))
return;
else
soapHeader.AppendChild(CreateCustomHeader(soapHeader, "1"));
MemoryStream result = new MemoryStream(ZipWrapper.Compress(Encoding.UTF8.GetBytes(envelope.Body.InnerXml)));
Microsoft.Web.Services2.Attachments.Attachment attch = new Microsoft.Web.Services2.Attachments.Attachment("APPLICATION/OCTET-STREAM", result);
envelope.Context.Attachments.Add(attch);
XmlElement newBody = envelope.CreateBody();
newBody.RemoveAll();
envelope.SetBodyObject(newBody);
}
创建一个Web服务项目。在解决方案资源管理器中右键单击项目,选择WSE 2.0设置。在常规选项卡中,启用两个复选框。添加对WebServiceZipFilter.dll的引用。在web.config文件中,添加以下内容:
<microsoft.web.services2>
<filters>
<output>
<add type="WebServiceZipFilter.ZipFilter, WebServiceZipFilter" />
</output>
</filters>
</microsoft.web.services2>
为了配置过滤器,应该设置其属性:
WebServiceZipFilter.ZipFilter.MinFilterSizeKB = 10;
WebServiceZipFilter.ZipFilter.Enabled = true;
注意:强烈建议通过web.config中的可配置部分设置这些值,以便根据调整需求动态更改。
创建一个WinForms客户端项目。在解决方案资源管理器中右键单击项目,选择WSE 2.0设置。在常规选项卡中,启用第一个复选框。添加服务器的Web引用。创建服务器代理(实例化ServerNameWSE代理类)。在代理服务器创建后添加以下代码:
TestServer.Service1Wse myServer = new TestClient.TestServer.Service1Wse();
myServer.Pipeline.InputFilters.Add(new WebServiceZipFilter.UnZipFilter());
在本地的一个专用服务器上进行了测试,该服务器位于家乡的Web农场中,提供5MB的下载速度和1MB的上传速度,使用ADSL 750KB的连接,在周末中午放松的时候,条件非常适合非压缩测试,但即使如此,差异仍然相当明显:
还会有新版本吗?显然不会。这是好消息吗?是的!为什么?因为Redmond的人们意识到缺少压缩功能,一些优秀的人发布了WCF实现,这些人还发布了WSE 3.0的版本,所以任务已经完成了。每个人都很高兴。