在ASMX中解压缩传入的HTTP SOAP请求

时间:2017-11-14 09:47:46

标签: c# asp.net web-services asmx

我正在尝试让IIS接受压缩的SOAP / XML 请求

似乎IIS不支持开箱即用的压缩HTTP 请求。任何带有{# {{ var }} #} Content-Encoding: gzip的HTTP请求都会返回HTTP错误400。

所以我尝试通过<{3}}中描述的 Global.asax 添加deflate

Global.asax中

DelegatingHandler

但是在 ASMX 的情况下,似乎没有执行MessageHandler(我已经检查过,protected void Application_Start() { GlobalConfiguration.Configuration.MessageHandlers.Add(new DecompressionHandler()); } 被调用,但是整个WebApi配置似乎都有在ASMX中没有效果。)

所以问题是 - 如何在 ASMX 服务中实施 SOAP 请求解压缩?

1 个答案:

答案 0 :(得分:0)

能够让它与SoapExtension

一起使用
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Services.Protocols;

/// <summary>
///   ASPX SOAP request decompression WebMethod annotation
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class CompressedRequestAttribute : SoapExtensionAttribute
{
  public override Type ExtensionType { get { return typeof(CompressedRequestExtension); } }
  public override int Priority { get { return 0; } set { } }
}

/// <summary>
///   ASPX SOAP request decompression implementation
/// </summary>
public class CompressedRequestExtension : SoapExtension
{
  public override object GetInitializer(Type serviceType) { return null; }

  public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute) { return null; }

  public override void Initialize(object initializer) { }

  Stream origStream;
  StreamDelegate wrappedStream = new StreamDelegate();

  public override void ProcessMessage(SoapMessage message) {
    switch (message.Stage) {
      case SoapMessageStage.BeforeDeserialize:
        if (message.ContentEncoding == "gzip") {
          wrappedStream.wrapped = new GZipStream(origStream, CompressionMode.Decompress, true);
          message.ContentEncoding = null;
        }
        else if (message.ContentEncoding == "deflate") {
          wrappedStream.wrapped = new DeflateStream(origStream, CompressionMode.Decompress, true);
          message.ContentEncoding = null;
        }
        else {
          goto default;
        }
        break;
      default:
        wrappedStream.wrapped = origStream;
        break;
    }
  }

  public override Stream ChainStream(Stream stream) {
    origStream = stream;
    return wrappedStream;
  }

}

public class StreamDelegate : Stream
{
  public Stream wrapped;
  public override bool CanRead { get { return wrapped.CanRead; } }
  public override bool CanSeek { get { return wrapped.CanSeek; } }
  public override bool CanWrite { get { return wrapped.CanWrite; } }
  public override long Length { get { return wrapped.Length; } }
  public override long Position { get { return wrapped.Position; } set { wrapped.Position = value; } }
  public override void Flush() { wrapped.Flush(); }
  public override int Read(byte[] buffer, int offset, int count) { return wrapped.Read(buffer, offset, count); }
  public override long Seek(long offset, SeekOrigin origin) { return wrapped.Seek(offset, origin); }
  public override void SetLength(long value) { wrapped.SetLength(value); }
  public override void Write(byte[] buffer, int offset, int count) { wrapped.Write(buffer, offset, count); }
}

然后使用:

为每个WebMethod添加注释
  [CompressedRequestAttribute]

证明它有效:

POST /TestService/TestAction1.asmx HTTP/1.1
Host: localhost
Accept-Encoding: deflate, gzip
SOAPAction: http://example.com/TestService:action1
Content-Type: text/xml;charset=UTF-8
Content-Encoding: gzip
Content-Length: 321

<gzipped-request>

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
Content-Encoding: gzip
Content-Length: 10193

<gzipped-response>