Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
392 views
in Technique[技术] by (71.8m points)

asp.net mvc - Compression filter for Web API

I've been using the compression filter for my MVC actions as detailed here:

http://msdn.microsoft.com/en-us/magazine/gg232768.aspx

I've tried to re-purpose the code to do something similar for Web API, but I've hit a roadblock:

public class CompressAPIAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext filterContext)
    {
        var preferredEncoding = GetPreferredEncoding(filterContext.Request);
        Stream compressedStream = null;
        // Compress the response accordingly
        var response = filterContext.Response;
        response.Headers.Add("Content-encoding", preferredEncoding.ToString());

        if (preferredEncoding == CompressionScheme.Gzip)
        {
            response.Content = new GZipStream(compressedStream, CompressionMode.Compress); //THIS WON'T WORK
        } 

        if (preferredEncoding == CompressionScheme.Deflate)
        {
            response.Content = new DeflateStream(compressedStream, CompressionMode.Compress); //THIS WON'T WORK
        }
        return;
    }

    enum CompressionScheme
    {
        Gzip = 0,
        Deflate = 1,
        Identity = 2
    }

    private CompressionScheme GetPreferredEncoding(HttpRequestMessage request)
    {
        var acceptableEncoding = request.Headers.AcceptEncoding;

        if (acceptableEncoding.Where(h => h.Value.Contains("gzip")).Count() > 0)
            return CompressionScheme.Gzip;

        if (acceptableEncoding.Where(h => h.Value.Contains("deflate")).Count() > 0)
            return CompressionScheme.Deflate;

        return CompressionScheme.Identity;
    }

Any ideas how I can assign a compressed stream to the response's content?

I should point out this is being hosted in IIS 6.0, which I do not control.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think you should not do this in an action filter as the modelbinding stage happens before action filters are executed and during modelbinding the formatters could be reading the stream to deserialize it, in which case it would fail.

If you are using IIS, then do the following to setup compression(The following have some snippets from Scott Hanselman's blog post):

  • Enabled the "Dynamic Compression" feature in IIS.

  • Back in IIS Manager, go to the page for the SERVER, not the SITE. Click on Configuration Editor: enter image description here

  • From the dropdown, select system.webServer/httpCompression: enter image description here

  • Then click on Dynamic Types and now that you're in the list editor, think about what types you want compressed. By default / is False, but you could just turn that on. I chose to be a little more picky and added application/atom+xml, application/json, and application/atom+xml;charset=utf-8 as seen below. It's a little gotcha that application/atom+xml and application/atom+xml;charset=utf-8 are separate entries. Feel free to add what ever mimeTypes you like in here. enter image description here
  • After you've added them and closed the dialog, be sure to click Apply and Restart your IIS Service to load the new module.
  • Now make requests using Accept-Encoding header and you should see the response as expected.

  • EDIT ( in addition to above include "application/json; charset=utf-8" to cover both json formats)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...