Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bind C# ASP.NET's IFormFile with JS's File #5138

Open
mgirolet-gl opened this issue Apr 8, 2025 · 0 comments
Open

Bind C# ASP.NET's IFormFile with JS's File #5138

mgirolet-gl opened this issue Apr 8, 2025 · 0 comments

Comments

@mgirolet-gl
Copy link

mgirolet-gl commented Apr 8, 2025

Is your feature request related to a problem? Please describe.

When I make a in a web page that includes uploading a file, I might want to send that file to my C# ASP.NET API using my NSwag-generated client.

Here's the deal, though: web standards will give you a File instance to work with, which you are meant to send through FormData to your endpoint.

When using ASP.NET's FromFormAttribute, the file will automatically be parsed into a FormFile instance (which implements the IFormFile interface).

As such, the following works:

/* JS CLIENT SIDE */ 

let someFormElement: number = /* ... */;
let someOtherFormElement: string = /* ... */;
let myFileFormElement: File = /* ... */;

const formData = new FormData();
const headers = new Headers();
headers.set('Accept', 'application/json');
headers.delete('Content-Type');
formData.append('someFormElement', someFormElement.toString());
formData.append('someOtherFormElement', someOtherFormElement);
formData.append('file', myFileFormElement);

const uploadReq = new HttpRequest("POST", apiRoot + "/MyController/UploadMyCoolFile", formData, { reportProgress: true });
this.httpClient.request(uploadReq).subscribe(event => { /* ... */ });
/* C# ASP.NET SERVER SIDE */ 

public bool UploadMyCoolFile([FromForm] int someFormElement, [FromForm] string someOtherFormElement, [FromForm] IFormFile myFileFormElement) {
    // Deal with form elements
}

Point is, by doing it like this, the web browser loads the file solely to send it, and therefore doesn't have to store the entire file within the web page's memory. It loads it, sends it, unloads it, which is the recommended way of sending files and avoids freezes and high memory usage for big files.

However, when using NSwag to generate a TS client to use that instead of manually creating my FormData, the following is generated:

         {
            "type": "string",
            "name": "ContentType",
            "in": "formData",
            "x-nullable": false
          },
          {
            "type": "string",
            "name": "ContentDisposition",
            "in": "formData",
            "x-nullable": false
          },
          {
            "type": "object",
            "name": "Headers",
            "in": "formData",
            "x-schema": {
              "$ref": "#/definitions/IHeaderDictionary"
            },
            "x-nullable": false
          },
          {
            "type": "integer",
            "name": "Length",
            "in": "formData",
            "format": "int64",
            "x-nullable": false
          },
          {
            "type": "string",
            "name": "Name",
            "in": "formData",
            "x-nullable": false
          },
          {
            "type": "string",
            "name": "FileName",
            "in": "formData",
            "x-nullable": false
          }

Which defeats the point, it essentially puts all of IFormFile's properties as parameters, but that's not what we want here, if can't pass the native DOM File type to this.

Describe the solution you'd like

It would be nice if NSwag understood that any type that implements IFormFile on the C# side should become a File on the JS/TS side.

Describe alternatives you've considered

  • Loading the whole file on the web browser and uploading it as a byte array: very bad for huge files
  • Adding some kind of override to the OperationProcessorContext to replicate the desired behaviour: I couldn't find a way to do that, even using JsonObjectType.File gives some other type that would require loading the file beforehand
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant