【发布时间】:2018-07-03 16:08:53
【问题描述】:
我有一个生成 JSON 和 XML 响应的 ASP.NET Core 服务。但是,我喜欢将接受的媒体类型限制为仅一种操作,因此 Swagger 只能将 application/json 列为有效的响应内容类型。如何在 ASP.Net Core 中实现这一点?
请考虑我使用的是 ASP.Net Core (ASP.NET MVC 6),而不是 ASP.NET WebAPI。
更新
好的,所以我会将答案添加为同一问题的一部分。感谢@Helen,我能够在 ASP.Net Core (ASP.Net MVC 6) 中添加所需的类来实现这一点。答案基于this answer,但修改为使用 ASP.NET Core 类。
第 1 步。 创建自定义操作过滤器属性,以便管道对禁止的内容类型做出反应:
/// <summary>
/// SwaggerResponseContentTypeAttribute
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public sealed class SwaggerResponseContentTypeAttribute : ActionFilterAttribute
{
/// <summary>
/// SwaggerResponseContentTypeAttribute
/// </summary>
/// <param name="responseType"></param>
public SwaggerResponseContentTypeAttribute(string responseType)
{
ResponseType = responseType;
}
/// <summary>
/// Response Content Type
/// </summary>
public string ResponseType { get; private set; }
/// <summary>
/// Remove all other Response Content Types
/// </summary>
public bool Exclusive { get; set; }
public override void OnActionExecuting(ActionExecutingContext context)
{
var accept = context.HttpContext.Request.Headers["accept"];
var accepted = accept.ToString().ToLower().Contains(ResponseType.ToLower());
if (!accepted)
context.Result = new StatusCodeResult((int)HttpStatusCode.NotAcceptable);
}
}
第 2 步。创建一个 Swagger 操作过滤器,以便 UI 可以反映限制
public class ResponseContentTypeOperationFilter : IOperationFilter
{
public void Apply(Swashbuckle.AspNetCore.Swagger.Operation operation, OperationFilterContext context)
{
var requestAttributes = context.ControllerActionDescriptor.GetControllerAndActionAttributes(true).Where(c=>c.GetType().IsAssignableFrom(typeof(SwaggerResponseContentTypeAttribute))).Select(c=> c as SwaggerResponseContentTypeAttribute).FirstOrDefault();
if (requestAttributes != null)
{
if (requestAttributes.Exclusive)
operation.Produces.Clear();
operation.Produces.Add(requestAttributes.ResponseType);
}
}
}
第 3 步。 在 Startup.cs 中的 ConfigureServices 方法中配置 Swagger UI 服务,以便它可以使用新创建的操作过滤器。
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.Configure<MvcOptions>(options =>
{
options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
});
// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
c.OperationFilter<ResponseContentTypeOperationFilter>();
});
}
第 4 步。注释动作
// GET api/values
[HttpGet]
[WebService.Utils.SwaggerResponseContentType(responseType: "application/json", Exclusive = true)]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
【问题讨论】:
-
@Helen 感谢您的链接。答案与 ASP.Net Web API 有关。但是,通过一些小的修改,它可以迁移到 ASP.Net Core。不过,这只能解决 Swagger 只会显示 application/json 的问题,但在后台,我仍然可以使用 Accept: application/xml 执行请求,它会起作用。我想实际限制控制器操作中接受的媒体类型。
-
options.OutputFormatters.RemoveType<XmlDataContractSerializerOutputFormatter>()呢? -
关键是我希望 XML 序列化程序普遍可用。我只是希望它不适用于特定操作。
标签: asp.net asp.net-core swagger-ui media-type