使用未在swagger中公开的HTTP内容进行API文件上载

时间:2017-02-24 09:58:57

标签: c# api swagger

我正在为现有的Web API实现一个swagger接口。当前API控制器公开异步上载功能,该功能使用Request.Content异步传输图像。已使用的代码在this文章中进行了解释。

我的api控制器:

    [HttpPost]
    [Route("foo/bar/upload")]
    public async Task<HttpResponseMessage> Upload()
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
        var provider = await Request.Content.ReadAsMultipartAsync(new InMemoryMultipartFormDataStreamProvider());
        NameValueCollection formData = provider.FormData;
        HttpResponseMessage response;
        //access files  
        IList<HttpContent> files = provider.Files;
        if (files.Count > 0)
        {
            HttpContent file1 = files[0];
            using (Stream input = await file1.ReadAsStreamAsync())
            {
                object responseObj = ExternalProcessInputStream(input)
                response = Request.CreateResponse(HttpStatusCode.OK, responseObj);
            }
        }
        else 
        {
            response = Request.CreateResponse(HttpStatusCode.BadRequest);
        }
        return response;
    }

这有点花花公子,但是当我通过招摇暴露这个时,我有一个无参数函数,它在使用时会返回错误。

我的问题是如何提供适当的值来测试这个方法?

1 个答案:

答案 0 :(得分:7)

您需要添加自定义IOperationFilter来处理此问题。

鉴于你有一个像这样的控制器:

    [ValidateMimeMultipartContentFilter]
    [HttpPost, Route("softwarepackage")]
    public Task<SoftwarePackageModel> UploadSingleFile()
    {

        var streamProvider = new MultipartFormDataStreamProvider(ServerUploadFolder);
        var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<SoftwarePackageModel>(t =>
        {
            var firstFile = streamProvider.FileData.FirstOrDefault();

            if (firstFile != null)
            {
                // Do something with firstFile.LocalFileName
            }

            return new SoftwarePackageModel
            {

            };
        });

        return task;
    }

然后,您需要创建一个Swashbuckle.Swagger.IOperationFilter,将文件上传参数添加到您的函数中,如:

    public class FileOperationFilter : IOperationFilter
    {
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            if (operation.operationId.ToLower() == "softwarepackage_uploadsinglefile")
            {
                if (operation.parameters == null)
                    operation.parameters = new List<Parameter>(1);
                else
                    operation.parameters.Clear();
                operation.parameters.Add(new Parameter
                {
                    name = "File",
                    @in = "formData",
                    description = "Upload software package",
                    required = true,
                    type = "file"
                });
                operation.consumes.Add("application/form-data");
            }
        }
    }

在您的Swagger配置中,您需要注册过滤器:

config.EnableSwagger(c => {... c.OperationFilter<FileOperationFilter>(); ... });

为了做到这一点,我还添加了一个FilterAttribute来过滤掉Multipart内容:

public class ValidateMimeMultipartContentFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {

    }

}