RicoSuter/NSwag

Generating with FormFile or FormFileCollection (binary) does not work

geskill opened this issue · 0 comments

Latest tested version: v14.1.0
Latest working version: v13.20

IFormFile, FormFile or any derived types in collection or list etc.

public async virtual Task<IActionResult> Upload( [FromForm] ICollection<IFormFile> files ) {

v13

upload(files: FileParameter[] | null | undefined): Observable<XYZ> {

//...
        const content_ = new FormData();
        if (files !== null && files !== undefined)
            files.forEach(item_ => content_.append("files", item_.data, item_.fileName ? item_.fileName : "files") );
//...

export interface FileParameter {
    data: any;
    fileName: string;
}

v14

upload(files: string[] | null | undefined): Observable<XYZ> {

//...
        const content_ = new FormData();
        if (files !== null && files !== undefined)
            files.forEach(item_ => content_.append("files", item_.data, item_.fileName ? item_.fileName : "files") );
// this creates errors in the generated typescript file

// the interface FileParameter etc. is not created

It seems the FormFile is converted to a string.

This was an issue before: #2983

IFormFileCollection

public async virtual Task<IActionResult> Upload( [FromForm] IFormFileCollection files ) {

v14

upload(files: any[] | null | undefined): Observable<XYZ> {

//...
        const content_ = new FormData();
        if (files !== null && files !== undefined)
            files.forEach(item_ => content_.append("files", item_.toString()));
// this creates errors in the function call since toString() is not correct here

// the interface FileParameter etc. is not created

Partial working with FormFileCollection // workaround

public async virtual Task<IActionResult> Upload( [FromForm] FormFileCollection files ) {

v14

upload(files: FileParameter[] | null | undefined): Observable<XYZ> {

//...
        const content_ = new FormData();
        if (files !== null && files !== undefined)
            files.forEach(item_ => content_.append("files", item_.data, item_.fileName ? item_.fileName : "files") );

However, the interface FileParameter is not created, as a workaround create a class FileParameter and add this manually:

public class AddAdditionalTypeProcessor : IOperationProcessor {
    public Type Type { get; }

    public AddAdditionalTypeProcessor( Type type ) {
        Type = type;
    }
    public bool Process( OperationProcessorContext context ) {
        context.SchemaGenerator.Generate( Type.ToContextualType(), context.SchemaResolver );
        return true;
    }
}

....OperationProcessors.Add( new AddAdditionalTypeProcessor( typeof( FileParameter ) ) );
    public class FileParameter {
        public string FileName { get; set; }
        public object Data { get; set; }
    }