0

I would like to configure the uploadable file size of the request from the appsettings.json on every controller method with different parameter, but I don't want to set it globally. How can I do it?


public long GetCatMaxFileUploadSize()
{
    return _appSettings.Value.CatSettings.GetUploadFileSize;
}

public long GetDogMaxFileUploadSize()
{
    return _appSettings.Value.DogSettings.GetUploadFileSize;
}

public long GetRabbitMaxFileUploadSize()
{
    return _appSettings.Value.RabbitSettings.GetUploadFileSize;
}

...

[HttpPost]
[RequestSizeLimit(1000000)] //1MB -> set this value "dynamically" from appsettings.json
[RequestFormLimits(MultipartBodyLengthLimit = 1000000)]
public IActionResult CatConfigUploader([FromForm] IFormFile jSonFile){
    ...
}

[HttpPost]
[RequestSizeLimit(50000000)] //50MB -> set this value "dynamically" from appsettings.json
[RequestFormLimits(MultipartBodyLengthLimit = 50000000)]
public IActionResult DogConfigUploader([FromForm] IFormFile jSonFile){
    ...
}

[HttpPost]
[RequestSizeLimit(4000000)] //4Mb -> set this value "dynamically" from appsettings.json
[RequestFormLimits(MultipartBodyLengthLimit = 4000000)]
public IActionResult RabbitConfigUploader([FromForm] IFormFile jSonFile){
    ...
}

(I know, if I change the value in appsettings I have to restart the IIS, but this is better, than recompile the file.)

vizvezetek
  • 51
  • 4

1 Answers1

1

C# attribute is a compile-time construct, which means that all attribute parameters must be known at compile time. appsettings.json is a run-time thing, because it is loaded when the application starts. At this point the values for attributes must have already been set. So, the short answer, you cannot do this.

The long answer would be to use some kind of code generation tool. E.g. you could define your API in Swagger and let the C# code be generated with SwaggerCode Gen. The templates you can edit, and you could read out values from appsettings. This would require quite some work and is beyond the scope of this answer.

Here is a nice discussion specifically on the request size limit. You could probably use middleware to achieve what you want.

Edit:

In a middleware:

void MyMiddleware(/*inject settings*/){}

public async Task Invoke(HttpContext httpContext)
{
  var limit = SOME_LIMIT_FROM_SETTINGS;
  var path = httpContext.Request.Path;
  if (path.IsThisAndThat()){
    limit = ANOTHER_LIMIT_FROM_SETTINGS;
  }

  if (httpContext.Request.ContentLength > limit)
  {
    throw ... ;    
  }
}
Maxim Zabolotskikh
  • 3,091
  • 20
  • 21
  • Thank you for your answer. I know how working the c# attributes and because of this I could not solve the problem. I also tried the middleware and the other solutions too, but all of the working methods sets the request size globally, and not only for one method. – vizvezetek Feb 22 '22 at 08:32
  • What about "Generic Middleware Instructions" in the link I posted? You could read the URL path from HttpContext and adjust the max body size accordingly – Maxim Zabolotskikh Feb 22 '22 at 09:16