首页 > 解决方案 > 从控制器方法中删除媒体类型

问题描述

我有一个控制器,其中包含许多生成application/vnd.api+jsonapplication/json. 我有一种支持application/json-patch+json.

为了避免 getter 方法上的重复属性,我[Produces]在类级别有一个

[Produces("application/json", "application/vnd.api+json")]
public class ValuesController : Controller
{ ... }

这很好,但是当查看生成的 Swagger UI 文档页面时,补丁说它支持上述所有 3 种媒体类型,这是错误的。

所以,我想要一种方法来删除应用于补丁方法的两个。我试图有效地创建与[Produces].

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DoesNotProduceAttribute : Attribute, IApiDefaultResponseMetadataProvider, IOrderedFilter
{
    public DoesNotProduceAttribute(string contentTypeToRemove, params string[] otherContentTypesToRemove)
    {
        ContentTypes.Add(contentTypeToRemove);
        otherContentTypesToRemove.ForEach(ContentTypes.Add);
    }

    public void SetContentTypes(MediaTypeCollection contentTypes)
    {
        foreach (var contentType in ContentTypes)
            contentTypes.Remove(contentType);
    }

    public MediaTypeCollection ContentTypes { get; } = new MediaTypeCollection();
    ...
}

并将其应用于我的方法

[HttpPatch("{id}")]
[DoesNotProduce("application/json", "application/vnd.api+json")]
public async Task<IActionResult> Update(string id, [FromBody]JsonPatchDocument<Value> patchDocument)
{ ... }

但是SetContentTypes()没有调用该方法。我错过了什么?是否有另一种方法可以删除我不想要的补丁方法的内容类型?

标签: c#asp.net-core

解决方案


您可以使用ResultFilterAttribute并覆盖在操作执行后立即触发的 OnResultExecuted 方法。这样,您就可以从返回给 api 使用者的 ObjectResult 中删除内容类型。

筛选:

public class RemoveContentTypeAttribute : ResultFilterAttribute {
    public MediaTypeCollection ContentTypes { get; } = new MediaTypeCollection();

    public RemoveContentTypeAttribute(string contentType, params string[] otherContentTypes) {
        ContentTypes.Add(contentType);
        foreach (var currentContentType in otherContentTypes) {
            ContentTypes.Add(currentContentType);
        }
    }

    public override void OnResultExecuted(ResultExecutedContext context) {
        var result = (ObjectResult)context.Result;
        foreach (var contentType in ContentTypes) {
            result.ContentTypes.Remove(contentType);
        }
    }
}

控制器

[RemoveContentType("application/json", "application/vnd.api+json")]
public async Task<IActionResult> Update(string id, [FromBody]JsonPatchDocument<Value> patchDocument)
{ ... }

推荐阅读