我目前正在将我的一些MVC3控制器迁移到MVC4 API控制器。我已经实现了 MVC3 控制器的压缩机制 通过固有ActionFilterAttribute
和覆盖方法获取方法响应OnActionExecutiong
。经过一番研究,我发现我需要使用System.Web.HttpFilters
的ActionFilterMethod
。如果有人可以分享一段示例代码来让我开始使用 GZip
现在剩下的就是在Application_Start
中注册处理程序:
GlobalConfiguration.Configuration.MessageHandlers.Add(new CompressHandler());
如果您使用的是IIS 7+,我会说将压缩留给IIS,因为它支持GZIP压缩。只需将其打开即可。
另一方面,压缩对于控制器来说太靠近金属。理想情况下,控制器应该在比字节和流高得多的级别上工作。
使用类并编写以下代码
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CompressFilter : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext context)
{
var acceptedEncoding = context.Response.RequestMessage.Headers.AcceptEncoding.First().Value;
if (!acceptedEncoding.Equals("gzip", StringComparison.InvariantCultureIgnoreCase)
&& !acceptedEncoding.Equals("deflate", StringComparison.InvariantCultureIgnoreCase))
{
return;
}
context.Response.Content = new CompressedContent(context.Response.Content, acceptedEncoding);
}
}
现在创建另一个类并编写以下代码。
public class CompressedContent : HttpContent
{
private readonly string _encodingType;
private readonly HttpContent _originalContent;
public CompressedContent(HttpContent content, string encodingType = "gzip")
{
if (content == null)
{
throw new ArgumentNullException("content");
}
_originalContent = content;
_encodingType = encodingType.ToLowerInvariant();
foreach (var header in _originalContent.Headers)
{
Headers.TryAddWithoutValidation(header.Key, header.Value);
}
Headers.ContentEncoding.Add(encodingType);
}
protected override bool TryComputeLength(out long length)
{
length = -1;
return false;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
Stream compressedStream = null;
switch (_encodingType)
{
case "gzip":
compressedStream = new GZipStream(stream, CompressionMode.Compress, true);
break;
case "deflate":
compressedStream = new DeflateStream(stream, CompressionMode.Compress, true);
break;
default:
compressedStream = stream;
break;
}
return _originalContent.CopyToAsync(compressedStream).ContinueWith(tsk =>
{
if (compressedStream != null)
{
compressedStream.Dispose();
}
});
}
}
现在在控制器或任何像这样的 api 操作方法中使用以下属性
[Route("GetData")]
[CompressFilter]
public HttpResponseMessage GetData()
{
}