在我的ASP.NET Web API应用程序中,我有一个这样的控制器:
[RoutePrefix("api/ratings")]
public class RateCostumerController : ApiController
{
[AllowAnonymous]
[Route("Report/GetReport")]
[HttpGet]
public HttpResponseMessage ExportReport([FromUri] string costumer)
{
var rd = new ReportDocument();
/*No relevant code here*/
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(ms.ToArray())
};
result.Content.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = "Reporte.pdf"
};
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
}
}
因此,当我使用客户参数发出简单的GET请求时,我会在浏览器中获得一个pdf文件作为响应。一些响应标头:
内容配置:附件;filename=Reporte。pdf属性长度:22331属性类型:应用程序/八位字节流
设置 swagger 后,在我的 Xamarin PCL 项目中生成 json 元文件并生成 C# 代码,我尝试使用该服务。但它失败了,因为在生成的代码中试图反序列化json,但不是json结果!
在这里,它是生成的代码的一部分,它失败了:
[...]
var _result = new Microsoft.Rest.HttpOperationResponse<object>();
_result.Request = _httpRequest;
_result.Response = _httpResponse;
// Deserialize Response
if ((int)_statusCode == 200)
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
_result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject<object>(_responseContent, this.Client.DeserializationSettings);
}
catch (Newtonsoft.Json.JsonException ex)
{
_httpRequest.Dispose();
if (_httpResponse != null)
{
_httpResponse.Dispose();
}
throw new Microsoft.Rest.SerializationException("Unable to deserialize the response.", _responseContent, ex);
}
}
if (_shouldTrace)
{
Microsoft.Rest.ServiceClientTracing.Exit(_invocationId, _result);
}
return _result;
[...]
当我调试时,我发现文件的内容在主体中,所以反序列化会把它搞乱。由于不建议编辑此生成的类文件,我需要在API中进行哪些更改,以正确生成应用程序/八位字节流内容响应的代码?
对于Swashbuckle版本4,我创建过滤器:
public class FileDownloadOperation : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
var rt = context.MethodInfo.ReturnType;
if (rt == typeof(Stream) ||
rt == typeof(Task<Stream>) ||
rt == typeof(FileStreamResult) ||
rt == typeof(Task<FileStreamResult>))
{
operation.Responses["200"] = new Response
{
Description = "Success", Schema = new Schema {Type = "file"}
};
operation.Produces.Clear();
operation.Produces.Add("application/octet-stream");
}
}
}
将其分配到摇摆发电机中
services.AddSwaggerGen(c =>
{
...
c.OperationFilter<FileDownloadOperation>();
});
然后只需使用简单的控制器:
[HttpGet("{fileId}")]
public async Task<FileStreamResult> GetMyFile(int fileId)
{
var result = await _fileService.GetFile(fileId);
return File(result.Stream, result.ContentType, result.FileName);
}
生成的代码将方法的输出视为 json,因为错误的类型写入了 swagger.json(可能是 .... #/definitions/....)。它应该包含“类型”:“文件”
您可以使用SwaggerGen选项来操作输出。
如果您的方法如下所示:
[Produces("application/pdf")]
[ProducesResponseType(200, Type = typeof(Stream))]
public IActionResult Download()
{
Stream yourFileStream = null; //get file contents here
return new FileStreamResult(yourFileStream , new MediaTypeHeaderValue("application/pdf"))
{
FileDownloadName = filename
};
}
在您的启动中,设置Swagger生成,配置您要返回的Type与您要出现在Swagger文件中的Type之间的映射
services.AddSwaggerGen(
options =>
{
options.MapType<System.IO.Stream>(() => new Schema { Type = "file" });
});
那么您生成的代码如下所示:
public async Task<HttpOperationResponse<System.IO.Stream>> DownloadWithHttpMessagesAsync()
创建返回文件的自定义筛选器:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public sealed class SwaggerFileResponseAttribute : SwaggerResponseAttribute
{
public SwaggerFileResponseAttribute(HttpStatusCode statusCode) : base(statusCode)
{
}
public SwaggerFileResponseAttribute(HttpStatusCode statusCode, string description = null, Type type = null) : base(statusCode, description, type)
{
}
public SwaggerFileResponseAttribute(int statusCode) : base(statusCode)
{
}
public SwaggerFileResponseAttribute(int statusCode, string description = null, Type type = null) : base(statusCode, description, type)
{
}
}
还有这个自定义的ResponseTypeFilter类:
public sealed class UpdateFileResponseTypeFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (apiDescription.GetControllerAndActionAttributes<SwaggerResponseRemoveDefaultsAttribute>().Any())
{
operation.responses.Clear();
}
var responseAttributes = apiDescription.GetControllerAndActionAttributes<SwaggerFileResponseAttribute>()
.OrderBy(attr => attr.StatusCode);
foreach (var attr in responseAttributes)
{
var statusCode = attr.StatusCode.ToString();
Schema responseSchema = new Schema { format = "byte", type = "file" };
operation.produces.Clear();
operation.produces.Add("application/octet-stream");
operation.responses[statusCode] = new Response
{
description = attr.Description ?? InferDescriptionFrom(statusCode),
schema = responseSchema
};
}
}
private string InferDescriptionFrom(string statusCode)
{
HttpStatusCode enumValue;
if (Enum.TryParse(statusCode, true, out enumValue))
{
return enumValue.ToString();
}
return null;
}
}
然后在 SwaggerConfig 文件中注册它:
c.OperationFilter<UpdateFileResponseTypeFilter>();
要使用此筛选器,只需将其添加到每个操作控制器中,如下所示:
[Route("Report/GetReport/{folio}")]
[SwaggerFileResponse(HttpStatusCode.OK, "File Response")]
[HttpGet]
public HttpResponseMessage ExportReport(string folio)
{
...
因此,当swagger生成json元数据时,autorest将正确地创建一个返回任务的方法
我不知道该用什么。我有两页——简介。jsp(1)和booksList.jsp(2)。对于每个页面,我都创建了一个控制器类。第一页有打开第二页的按钮: 第一个问题是:我不确定这个按钮的正确性。它工作得很好,但是按下这个按钮后我有问号。 第二个问题是:当我按下该按钮时,调用带有下一个注释的方法(第二页的控制器): 我应该用这种方法返回什么?换句话说,我怎么能从第一页跳到第二页? < li> < li>
我使用开放式api生成器(gradle的实现)为Java中的api生成控制器,但如果我的endpoint不返回任何内容,则OpenAPI生成器将返回类型生成为对象类型Void,而不是Void。 我希望: 但是得到了: 我试图自定义胡子模板,但没有任何选项。gradle任务配置中的ConfigOptions也没有相应的选项。 当前。小胡子api模板: 在gradle.build中生成任务示例 应用程
我得到这个错误消息: 无法写入JSON: 未找到用于java.io.FileDescriptor类的序列化程序,也未发现用于创建BeanSerializer的属性 (为了避免异常,禁用SerializationFeature.fail_on_empty_beans)) (通过引用链: org.springframework.core.io.filesystemResource[\“outputSt
生成一个 Http Controller 必选参数: -name 生成的 Controller 类名 -namespace 生成的 Controller 所在命名空间 可选参数: -prefix 路由前缀,不传则为类名 -render 渲染方式,默认为json,可选:html/json/xml -rest 是否生成 RESTful 风格,默认 false -override 是否覆盖已存在的文件,
几个星期以来,我一直在想办法解决这个问题,现在我开始放弃了。我肯定做了什么根本错误的事情。不管怎样,这是我的情况。我以前用JavaFX做了一个简单的小程序,但现在发现了Scene Builder,并想用这个工具重新构建它。该项目包括几个经常重用的组件,如下面的组件。它由一个标签、一个滑块、一个文本字段和另一个自定义组件InfoIcon组成。 我已经了解到,在构建我称之为SliderVariable