I'm working on a web app which uses a .NET web API to download a file. The request to the API is handled by client code generated using NSwag. This all works great locally, but when using the API that's hosted on Azure, the client code is unable to get the file name.
The client relies on the "Content-Disposition" response header to set the file name for the download. That header is automatically added by the API controller, which returns a FileContentResult. However, because "Content-Disposition" isn't a CORS-safelisted response header, the client isn't able to access it unless "Access-Control-Expose-Headers" is also provided to allow it.
Specifying this in the CORS policy in the API app's startup works great locally, but it seems the WithExposedHeaders
setting isn't respected when it's hosted on Azure.
Looking in the browser dev tools the "Content-Disposition" header is there with the expected file name, but "Access-Control-Expose-Headers" is not. The same request has both headers as expected when using the local API, though.
What is the proper way to expose the "Content-Disposition" header to my client from the Azure App Service?
Here's a simplified version of the relevant startup code:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.AllowAnyHeader();
builder.AllowAnyMethod();
builder.WithExposedHeaders("Content-Disposition");
});
});
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
And a simplified version of the API controller:
[HttpGet]
[Route("getfile")]
public async Task<ActionResult> GetFile(long id)
{
var file = await _fileService.GetFile(id);
return File(file.Content, file.MimeType, file.Name);
}
I thought the issue might be that the CORS settings defined on Azure override the app-defined policy, but clearing out all of the Azure CORS settings had no effect.
I also tried the setting suggested in this answer with "Content-Disposition" as the value, but it didn't appear to do anything. Not really sure that's even a valid setting as I can't find any other references to it besides that SO answer.
It seems like setting the exposed headers on Azure, as shown here, should be the answer but my App Service CORS config doesn't have those options. Guessing that may only apply to Azure Container Apps.
Additional research eventually led us to a solution. Short answer: the proper way to expose the "Content-Disposition" header from an API hosted as an Azure App Service depends on how the app is being accessed through Azure.