简体   繁体   中英

Compression Action Filter ASP.NET Core

I need to create Compression Action Filter using ASP.NET Core

I found some examples for MVC 5 like:

public class CompressAttribute : ActionFilterAttribute   {

public override void OnActionExecuting(ActionExecutingContext filterContext)
{

    var encodingsAccepted = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
    if (string.IsNullOrEmpty(encodingsAccepted)) return;

    encodingsAccepted = encodingsAccepted.ToLowerInvariant();
    var response = filterContext.HttpContext.Response;

    if (encodingsAccepted.Contains("deflate"))
    {
        response.AppendHeader("Content-encoding", "deflate");
        response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
    }
    else if (encodingsAccepted.Contains("gzip"))
    {
        response.AppendHeader("Content-encoding", "gzip");
        response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
    }
}  

But when I tried to use it with

using Microsoft.AspNet.Http;

It didn't work at all:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.Extensions.Primitives;

namespace App.Filterss
{
    public class CompressionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            HttpRequest request = context.HttpContext.Request;

            string acceptEncoding = request.Headers["Accept-Encoding"];

            if (string.IsNullOrEmpty(acceptEncoding)) return;

            acceptEncoding = acceptEncoding.ToUpperInvariant();

            HttpResponse response = context.HttpContext.Response;

            if (acceptEncoding.Contains("GZIP"))
            {
                response.Headers.Add("Content-Encoding", "gzip");
                response.Body = new GZipStream(response.Body, CompressionMode.Compress);
            }
            else if (acceptEncoding.Contains("DEFLATE"))
            {
                response.Headers.Add("Content-encoding", "deflate");
                response.Body = new DeflateStream(response.Body, CompressionMode.Compress);
            }
        }
    }
}

I just get 200 http responce with no content at all.

Can anybody tip me how to perform compressing using filter?

This is a new feature at ASP.net Core 1.1.

This is the packages you will need. https://www.nuget.org/packages/Microsoft.AspNetCore.ResponseCompression/

here is some official microsoft video showing how to use it: https://youtu.be/IfLg6LQCl-Y?t=223

some background information: https://github.com/aspnet/BasicMiddleware/issues/34

Code:

Project.json:

"dependencies": {
   ...,
   "Microsoft.AspNetCore.ResponseCompression": "1.0.0"
}

Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
//Add Middleware
app.UseResponseCompression();

....
}

public void ConfigureServices(IServiceCollection services)
{
//Configure Compression level
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);

//Add Response compression services
services.AddResponseCompression(options =>
{
    options.Providers.Add<GzipCompressionProvider>();
});
}

Check out rynowak 's answer on anGitHib issue for ASP.NET Core 1.0

1). If you're on IIS why not just use dynamic compression at the server level? https://technet.microsoft.com/en-us/library/cc753681%28v=ws.10%29.aspx

2). Our default streams are not intended to be read. By default we do some buffering in these streams, but we don't buffer the whole response because that would use an awful lot of memory. Once the amount of data we're willing to buffer has been written, it goes out on the wire and we don't store it any more. There are some techniques to enable buffering, and one of them is to replace the stream.

3). If you want to mess with the response stream for an MVC action (or all MVC actions), the right filter stage is a result filter ( IResultFilter or IAsyncResultFilter ).

Thing of it this way, calling View() in your controller is creating an IActionResult, which will be executed by MVC later, it's not actually executing the view inline, and that's why messing with the stream in that phase doesn't do what you want.

Result Filters actually surround the execution of the view code.

4). If you want to mess with the response stream for your whole application and don't want to/can't use gzip support provided by your server, then middleware is a good choice. (Compare to filters, which allow you to scope to Controller/Action).

If you still having issues with the middleware approach used above: have you tried setting a break point in the action in question to make sure it's actually hit? have you removed your action filter code (which wouldn't do what you want)?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM