【问题标题】:.net Core - Response type is ignored when add Filters.net Core - 添加过滤器时忽略响应类型
【发布时间】:2021-12-22 23:01:33
【问题描述】:

startup.cs 中,我为所有错误响应添加过滤器,bcs 我通过抛出异常返回自己的错误对象 (ErrorResponse),在中间件中我返回此代码作为响应。但是这些错误不是控制器方法中的返回类型,所以我必须为所有响应添加过滤器。它有效,在 swagger.json 中有这些响应,但没有响应类型 (200),只有错误响应。

services.AddMvc(options =>
{
 options.EnableEndpointRouting = false;
 options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ErrorResponse), (int)HttpStatusCode.BadRequest));
 options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ErrorResponse), (int)HttpStatusCode.Unauthorized));
 options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ErrorResponse), (int)HttpStatusCode.NotFound));
 options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ErrorResponse), (int)HttpStatusCode.InternalServerError));
})

有人知道如何保留控制器方法的默认返回类型吗?

谢谢。 :-)

【问题讨论】:

  • 使用ProducesResponseTypeAttributeActionResult<T> 作为返回类型
  • 我用这个 - public async Task<ActionResult<HorseEntity>> GetHorseById(int id) ,在 swagger.json 中不是这些类型,甚至 200 返回

标签: c# asp.net-core swagger


【解决方案1】:

虽然我不完全确定为什么过滤器最终会删除 ActionResult<T> 给出的默认 200 响应类型,但这是另一种可以完成的方法,尽管需要更多代码。此代码基于this answer

public class ProduceResponseTypeModelProvider : IApplicationModelProvider
{
    public int Order => 3;

    public void OnProvidersExecuted(ApplicationModelProviderContext context)
    {
    }

    public void OnProvidersExecuting(ApplicationModelProviderContext context)
    {
        var actions = context.Result.Controllers
            .SelectMany(x => x.Actions);

        foreach (var action in actions)
        {
            var returnType = action.ActionMethod.ReturnType;

            // if the action returns Task<T>, use that T as the return type
            if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
            {
                returnType = returnType.GenericTypeArguments[0];
            }

            // if returnType is an ActionResult<T>, use that T for a 200 OK response
            if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(ActionResult<>))
            {
                var innerReturnType = returnType.GetGenericArguments()[0];

                action.Filters.Add(new ProducesResponseTypeAttribute(innerReturnType, StatusCodes.Status200OK));
            }
            // otherwise, if the type is only IActionResult, return 204 No Content
            else if (returnType == typeof(IActionResult))
            {
                action.Filters.Add(new ProducesResponseTypeAttribute(StatusCodes.Status204NoContent));
            }

            // if there are input parameters, add 400 Bad Request as a possible result
            if (action.Parameters.Count > 0)
            {
                action.Filters.Add(new ProducesResponseTypeAttribute(typeof(ProblemDetails), StatusCodes.Status400BadRequest));
            }

            // add common response types
            action.Filters.Add(new ProducesResponseTypeAttribute(StatusCodes.Status401Unauthorized));
            action.Filters.Add(new ProducesResponseTypeAttribute(StatusCodes.Status403Forbidden));
            action.Filters.Add(new ProducesResponseTypeAttribute(StatusCodes.Status404NotFound));
            action.Filters.Add(new ProducesResponseTypeAttribute(StatusCodes.Status500InternalServerError));
        }
    }
}

应该相当简单地了解如何调整上述内容以返回 ErrorResponse 以获得特定响应。

上面可以注入:

services.TryAddEnumerable(ServiceDescriptor.Transient<IApplicationModelProvider, ProduceResponseTypeModelProvider>());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    • 2018-07-10
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多