首页 > 解决方案 > Postsharp DTO 请求验证和控制器范围的验证异常处理

问题描述

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

标签: c#aopwebapipostsharp

解决方案


没有代码示例有点不清楚您要使用 PostSharp 做什么。您似乎正在 ASP.NET Core (.NET 5) 中寻找一些典型的模型验证并返回自定义 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。


推荐阅读