【问题标题】:WebApi: Creating custom BadRequest status outside of ApiControllerWebApi:在 ApiController 之外创建自定义 BadRequest 状态
【发布时间】:2021-08-20 21:40:59
【问题描述】:

使用 .NET Core 2.0 WebApi。

我有一个 webapi,它有许多端点,每个端点都在处理并在失败时抛出 BadRequest。如下:

if(data == null)
{
   return BadRequest("Data must not be blank.");
}

现在,由于这些状态代码在我的 api 中重复出现,我正在考虑创建一个 Helper 方法,它将 BadRequest 返回到我的 API。

所以我创建了一个静态辅助类。但是这里的问题是 BadRequest 是 ControllerBase 的一部分,并且在我的帮助程序类中不可用。创建这个返回 BadRequest 的方法的最佳方法是什么。

--更新--

我想要这样的东西:

    public static BadRequest GetBadRequestMessage(string message)
    {
        return BadRequest(message);
    }

我也尝试过:

    public static BadRequestResult GetBadRequestMessage(string message)
    {
        return new  BadRequestResult(message);
    }

但这会产生错误:严重性代码描述项目文件行抑制状态 错误 CS1729 'BadRequestResult' 不包含采用 1 个参数的构造函数

【问题讨论】:

    标签: c# asp.net-core .net-core


    【解决方案1】:

    可以手动初始化动作结果

    return new BadRequestObjectResult("error message here");
    

    这基本上是 ControllerBase 在内部所做的

    /// <summary>
    /// Creates an <see cref="BadRequestResult"/> that produces a <see cref="StatusCodes.Status400BadRequest"/> response.
    /// </summary>
    /// <returns>The created <see cref="BadRequestResult"/> for the response.</returns>
    [NonAction]
    public virtual BadRequestResult BadRequest()
        => new BadRequestResult();
    
    /// <summary>
    /// Creates an <see cref="BadRequestObjectResult"/> that produces a <see cref="StatusCodes.Status400BadRequest"/> response.
    /// </summary>
    /// <param name="error">An error object to be returned to the client.</param>
    /// <returns>The created <see cref="BadRequestObjectResult"/> for the response.</returns>
    [NonAction]
    public virtual BadRequestObjectResult BadRequest(object error)
        => new BadRequestObjectResult(error);
    
    /// <summary>
    /// Creates an <see cref="BadRequestObjectResult"/> that produces a <see cref="StatusCodes.Status400BadRequest"/> response.
    /// </summary>
    /// <param name="modelState">The <see cref="ModelStateDictionary" /> containing errors to be returned to the client.</param>
    /// <returns>The created <see cref="BadRequestObjectResult"/> for the response.</returns>
    [NonAction]
    public virtual BadRequestObjectResult BadRequest(ModelStateDictionary modelState)
    {
        if (modelState == null)
        {
            throw new ArgumentNullException(nameof(modelState));
        }
    
        return new BadRequestObjectResult(modelState);
    }
    

    Source

    【讨论】:

    • 你的意思是从我的助手类返回“BadRequestObjectResult”吗?当我这样做时,它说“它不包含带有 1 个参数的构造函数”
    • @user1563677 源代码另有说明github.com/aspnet/Mvc/blob/master/src/…
    • 我已经用我尝试过的代码更新了我的帖子。不知道为什么它给出错误。即使我尝试在我的 api 控制器中使用它,您共享的代码也会出错。
    • @user1563677 我已经向您展示了源代码中的方法。你可以像他们在你的外部助手中那样做。重新检查我的答案中的代码,您应该会看到错误的位置。
    • 如果您将鼠标悬停在原始代码中的BadRequest 上,您将看到该方法不返回BadRequestResult,而是返回BadRequestObjectResult
    【解决方案2】:

    在 .net core 5 项目中,在您的 ioc 文件夹/类库中创建 BadRequestConfig 类:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.DependencyInjection;
    using System.Linq;
    
    namespace Ioc
    {
        public static class BadRequestConfig
        {
            // error 400 handling - remove extra fields in error model - remove if(ModelState.IsValid)
            public static IMvcBuilder AddBadRequestServices(this IMvcBuilder services)
            {
                services.ConfigureApiBehaviorOptions(options =>
                options.InvalidModelStateResponseFactory = actionContext =>
                {
                    var modelState = actionContext.ModelState.Values;
                    var allErrors = actionContext.ModelState.Values.SelectMany(v => v.Errors);
                    return new BadRequestObjectResult(new
                    {
                        StatusCode = 400,
                        Message = string.Join(" - ", allErrors.Select(e => e.ErrorMessage))
                    });
                });
    
                return services;
            }
        }
    }
    

    然后在你的 startup.cs 文件的 ConfigureServices 方法中添加 AddBadRequestServices() 方法:

    public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbServices();
            services.AddAppServices();
            services.AddControllers().AddBadRequestServices(); // here
            services.AddJwtAuthentication();
            services.AddSwaggerServices();
        }
    

    通过此解决方案,您无需在操作中编写 if(ModelState.IsValid)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-14
      • 2021-04-27
      • 2016-07-17
      • 1970-01-01
      相关资源
      最近更新 更多