简体   繁体   English

在 ASP.NET Core 控制器操作中限制接受的媒体类型

[英]Restrict accepted Media Types in ASP.NET Core Controller action

I have an ASP.NET Core Service that produces both JSON and XML responses.我有一个生成 JSON 和 XML 响应的 ASP.NET Core 服务。 However, I like to restrict the accepted Media Type for only one action, so Swagger can only list application/json as a valid response content type .但是,我喜欢将接受的媒体类型限制为仅一个操作,因此 Swagger 只能将 application/json 列为有效的响应内容类型 How can I achieve this in ASP.Net Core?如何在 ASP.Net Core 中实现这一点?

Please, consider I am using ASP.Net Core (ASP.NET MVC 6), not ASP.NET WebAPI.请考虑我使用的是 ASP.Net Core (ASP.NET MVC 6),而不是 ASP.NET WebAPI。

在此处输入图片说明

UPDATE更新

Ok, so I'll add the answer as part of the same question.好的,所以我会将答案添加为同一问题的一部分。 Thanks to @Helen, I was able to add the required classes to achieve this in ASP.Net Core (ASP.Net MVC 6).感谢@Helen,我能够在 ASP.Net Core (ASP.Net MVC 6) 中添加所需的类来实现这一点。 The answer is based on this answer but modified to use ASP.NET Core classes.答案基于此答案,但已修改为使用 ASP.NET Core 类。

Step 1. Create a custom action filter attribute so the pipeline reacts to a forbiden content type:步骤 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); 

    }

}

Step 2 .第 2 步 Create a Swagger Operation Filter so the UI can reflect the restriction创建一个 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);
        }
    }
}

Step 3. Configure Swagger UI service in Startup.cs, inside the method ConfigureServices, so it can use the newly created Operation Filter.步骤 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>();
        });
    }

Step 4 .第 4 步 Annotate the action注释动作

    // GET api/values
    [HttpGet]
    [WebService.Utils.SwaggerResponseContentType(responseType: "application/json", Exclusive = true)]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

You can use the annotations Consumes and Produces.您可以使用注释 Consumes 和 Produces。 These are also picked up by Swashbuckle.这些也被 Swashbuckle 收购。 Like so:像这样:

[HttpGet]
[Consumes("application/xml")]
[Produces("application/xml")]
public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM