Custom action filter attribute performs poorly when compared to RequestSizeLimit attribute

359 views Asked by At

I have a use-case when I need to limit the allowed request size for the file upload WebAPI endpoint. Normally I would use the in-built attribute RequestSizeLimit:

    [HttpPost]
    [RequestSizeLimit(104_857_600)] // 100mb limit
    public async Task<IActionResult> Upload([FromForm] IFormFile file) {

    }

However, per requirements I need to make the request size limit to be configurable and shared with rest of the application (for example with SPA application which uses the same value for it's own validation before user uploads the file, also with unit-tests etc..). So to cover this use-case I have implemented my own action filter:

public class CustomRequestSizeValidatorAttribute : ActionFilterAttribute
{
    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var request = context.HttpContext.Request;
        var contentLength = request.ContentLength;

        if (contentLength > SharedConsts.MaximumFileUploadSize)
        {
            var errorMessage = "Request content length is too large";
            context.Result = new BadRequestObjectResult(errorMessage);
        }
        else
        {
            await next();
        }
    }
}

And:

public static class SharedConsts
{
    public static readonly long MaximumFileUploadSize = 104_857_600; // 100 mb
}

And use it as:

    [HttpPost]
    [CustomRequestSizeValidator]
    public async Task<IActionResult> Upload([FromForm] IFormFile file) {

    }

And here comes the problem. I upload the 180mb file via Postman and here are the service response times:

  • without any of the 2 attributes ~ 2.5 - 3 seconds
  • with [CustomRequestSizeValidator] ~ same time (2.5 - 3 seconds)
  • with [RequestSizeLimit] ~ 22ms !

Why is my custom attribute [CustomRequestSizeValidator] so slow, as well as how to make the request execute just as fast as with the native attribute from MS [RequestSizeLimit]?

From the diagnostic tools I see that when [CustomRequestSizeValidator] attribute is used - memory consumption grows every time the request is made. With [RequestSizeLimit] attribute - memory never grows. So the problem is probably the Order in which logic is executed by the framework. My custom attribute is most likely executed as the very last step in the pipeline.. But I still have no idea how to fix it so any advices are welcomed.

0

There are 0 answers