Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.Net Core swagger Help Pages for IFormFile

I am trying to setup swagger for testing models which have IFormFile properties. For example I have next api method

[HttpPost]
public ApiResult<UserModel> SaveTestFileData([FromForm]TestPostFileArgs args)
{
    var result = new UserModel() { Id = 1, Name = $"SaveTestFileData {args.UserId} company: {args.CompanyId}, file length: {args.CompanyFile.Length}" };
    return ApiResult.Success(result);
}

And my parameter model

public class TestPostFileArgs
{
    public int UserId { get; set; }
    public int? CompanyId { get; set; }
    public IFormFile CompanyFile { get; set; }
}

By default swagger generate help page which does not allow to test it Wrong swagger ui To solve this problem I wrote next OperationFilter

public class FormFileOperationFilter: IOperationFilter
{
    public void Apply(Operation operation, OperationFilterContext context)
    {
        if (operation.Parameters == null)
            return;

        var fileParamNames = context.ApiDescription.ActionDescriptor.Parameters
            .SelectMany(x => x.ParameterType.GetProperties())
            .Where(x => x.PropertyType.IsAssignableFrom(typeof (IFormFile)))
            .Select(x => x.Name)
            .ToList();
        if (!fileParamNames.Any())
            return;

        var paramsToRemove = new List<IParameter>();
        foreach (var param in operation.Parameters)
        {
            paramsToRemove.AddRange(from fileParamName in fileParamNames where param.Name.StartsWith(fileParamName + ".") select param);
        }
        paramsToRemove.ForEach(x => operation.Parameters.Remove(x));
        foreach (var paramName in fileParamNames)
        {
            var fileParam = new NonBodyParameter
                {
                    Type = "file",
                    Name = paramName,
                    In = "formData"
                };
            operation.Parameters.Add(fileParam);
        }
        foreach (IParameter param in operation.Parameters)
        {
            param.In = "formData";
        }

        operation.Consumes = new List<string>() { "multipart/form-data" };
    }
}

And after this everething works as I expect from swagger. Correct swagger ui

For now this solution works for me, but it feels not right. Maybe I am missing some simple solution for this. Also this approach does not handle List or complex object properties with IFormFile or maybe something else.

like image 628
YuriyP Avatar asked Apr 27 '16 14:04

YuriyP


1 Answers

For you ASP.NET Core developers, there's an issue written up in the Swashbuckle.AspNetCore GitHub repo for this: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/193. It has some working code for an OperationFilter in the comments as well -- that one worked better for me than the other ones in this question.

like image 148
IGx89 Avatar answered Oct 05 '22 01:10

IGx89