【问题标题】:Postsharp DTO request validation & controller wide validation exception handlingPostsharp DTO 请求验证和控制器范围的验证异常处理
【发布时间】:2021-08-21 07:26:40
【问题描述】:

我正在尝试将 PostSharp 用于 WebAPI 项目。我无法完成这项任务。我想使用 PostSharp 合同来验证传入的 DTO 并在出现验证错误时集中异常处理。但我不知道如何在类级别应用异常方面,更糟糕的是如何在发生这种情况时返回 JSON 错误响应。

【问题讨论】:

  • 您在哪个平台上工作? ASP.NET 核心?您是否有一些您想要摆脱的代码示例(您当前的方法看起来如何?)?您是否查看过有关 intercepting method calls 的文档和示例?
  • 平台为.NET 5.0。我有一个要验证输入的控制器。为此,我使用了 PostSharp Contracts,并且抛出了无效请求的异常。只是似乎无法捕捉到任何异常,因为实际异常是在请求 DTO 类的设置器中引发的,该类通过 [FromBody] 属性在控制器方法中实例化。
  • 在控制器方法上处理异常不起作用,因为在抛出控制器方法之前抛出了异常。搜索“.net core 处理模型绑定异常”以找到挂钩此过程的方法。

标签: c# aop webapi postsharp


【解决方案1】:

如果没有代码示例,有点不清楚您要使用 PostSharp 做什么。您似乎正在 ASP.NET Core (.NET 5) 中寻找一些典型的 model validation 并返回自定义 JSON 响应(假设您正在使用 ASP.NET Web API)。

我知道您在询问 PostSharp,但我相信它需要一些自定义代码才能使其工作并在 ASP.NET 中返回自定义响应,而您可以通过 DataAnnotations 命名空间中的 ASP 本身免费获得大部分内容。

例子:

// CredentialsRequest.cs
using System.ComponentModel.DataAnnotations;
public class Credentials
{
    [Required]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    public string Password { get; set; }
}


// AuthenticationController.cs
[ApiController]
public class AuthenticationController : ControllerBase
{
    [HttpPost]
    public Task<IActionResult> Login([FromBody] Credentials credentials)
    {
        var result = // check `credentials` for valid login
        return result.Success
            ? Ok(result)
            : StatusCode(StatusCodes.Status401Unauthorized, result);
    }
}

要捕获所有模型验证错误,您可以在Startup.ConfigureServices 中添加以下响应工厂(根据自己的喜好自定义):

services.Configure<ApiBehaviorOptions>(config =>
{
    // Override default response when input model is invalid
    config.InvalidModelStateResponseFactory =
        ctx => new BadRequestObjectResult(new BaseResponse(
            success: ctx.ModelState.IsValid,
            errors: ctx.ModelState.Values
                .Where(v => v.ValidationState == ModelValidationState.Invalid)
                .SelectMany(v => v.Errors)
                .Select(e => new ErrorDetails
                {
                    Code = "ModelError",
                    Description = e.ErrorMessage
                })
                .ToList()
            ));
});

这里的BaseResponseErrorDetails 只是我用作所有响应数据模型的基础的一些简单数据模型/类:

public class BaseResponse
{
    public bool Success { get; }
    public List<ErrorDetails> Errors { get; }

    public BaseResponse(bool success, ErrorDetails error)
        : this(success, new List<ErrorDetails> { error })
    { }

    public BaseResponse(bool success, List<ErrorDetails> errors = null)
    {
        Success = success;
        Errors = errors;
    }
}

如果您尚未将 API 配置为以不同格式返回数据,则默认情况下应为 JSON。

【讨论】:

  • 感谢@Xerillio 提供这个详尽的示例。我知道 DataAnnotations,这正是我想要的,我只是尝试使用 PostSharp.Patterns.Contracts。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-13
  • 2022-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-03
相关资源
最近更新 更多