I have a FileContoller
which accepts large file uploads. To allow for files larger than 30Mb, I use the RequestSizeLimit
attribute, like so:
private const long _maxFileSize = 1000 * 1000 * 150; // 150 Mb
[HttpPost]
[RequestSizeLimit(_maxFileSize)]
public async Task<ActionResult<IList<UploadResult>>> PostFile([FromForm] IEnumerable<IFormFile> files)
{
// ....
}
This works, but I would like to put the hard coded file limit in a configuration file - which does not work when using the attribute.
Quite a few answers on this site, eg.
Define different APIs to accept different size limits in ASP.Net Core 2.2
suggest setting the limit by changing the middleware pipeline in Program.cs
, which opens up the possibility to read an injected configuration, like so:
app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>{
context.Features.Get<IHttpMaxRequestBodySizeFeature>()
.MaxRequestBodySize = 1000 * 1000 * 150; // 150 Mb;
//TODO: read hardcoded limit from configuration
});
But this doesn't even compile:
CS0103 - The name 'context' does not exist in the current context
How can I change the above to work in current version of .NET Core? I'm currently working on .NET 6 switching to .NET 8.
Alternatively, is there any other method to set the RequestSizeLimit
from configuration?
SOLUTION:
Thanks to Ahmad Pirouze, my final code looked like this:
var app = builder.Build();
const long _defaultMaxRequestBodySize = 1024 * 1024 * 75;
app.UseWhen(context => context.Request.Path.StartsWithSegments("/api/File"), appBuilder => {
appBuilder.Use(async (context, next) =>
{
var maxRequestBodySizeFeature = context.Features.Get<IHttpMaxRequestBodySizeFeature>() ?? throw new ArgumentNullException("IHttpMaxRequestBodySizeFeature");
maxRequestBodySizeFeature.MaxRequestBodySize = builder.Configuration.GetValue<long>("MaxRequestBodySize", _defaultMaxRequestBodySize);
await next.Invoke();
});
});
The reason why your code does not compile is that you are missing a parameter in the UseWhen method. The UseWhen method takes two parameters: a predicate function that returns a boolean value based on the HttpContext, and a configuration action that takes an IApplicationBuilder. You have only provided the first parameter, but not the second one. To fix this, you need to add a lambda expression that takes an IApplicationBuilder as a parameter and configures the middleware pipeline for the matching requests. For example:
app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
{
// This is the second parameter that you are missing
appBuilder.Use(async (context, next) =>
{
context.Features.Get<IHttpMaxRequestBodySizeFeature>()
.MaxRequestBodySize = 1000 * 1000 * 150; // 150 Mb;
//TODO: read hardcoded limit from configuration
await next.Invoke();
});
});
This way, you can set the MaxRequestBodySize feature for the requests that start with "/api" path segment. Note that you also need to invoke the next middleware in the pipeline by calling await next.Invoke().