You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 3.1 API接收无效GUID时的自定义异常处理

自定义.NET Core 3.1中JSON反序列化异常的错误返回

针对你遇到的Guid格式不匹配导致的默认400错误返回,以下是几种实现自定义错误信息的方案:

方案一:自定义JsonConverter+异常过滤器

这种方式通过自定义Guid类型的反序列化逻辑,抛出明确的错误信息,再通过异常过滤器捕获并返回自定义响应。

1. 创建自定义Guid转换器

public class GuidNullableConverter : JsonConverter<Guid?>
{
    public override Guid? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.Null)
            return null;

        string value = reader.GetString();
        if (string.IsNullOrWhiteSpace(value))
            return null;

        if (Guid.TryParse(value, out Guid guid))
            return guid;

        // 抛出带明确提示的异常
        throw new JsonException($"identification_guid必须是有效的GUID格式");
    }

    public override void Write(Utf8JsonWriter writer, Guid? value, JsonSerializerOptions options)
    {
        if (value.HasValue)
            writer.WriteStringValue(value.Value.ToString());
        else
            writer.WriteNullValue();
    }
}

2. 注册转换器并添加全局异常过滤器

在Startup.cs的ConfigureServices方法中:

services.AddControllers(options =>
{
    // 添加全局异常过滤器
    options.Filters.Add<CustomExceptionFilterAttribute>();
})
.AddJsonOptions(options =>
{
    // 注册自定义Guid转换器
    options.JsonSerializerOptions.Converters.Add(new GuidNullableConverter());
});

3. 实现异常过滤器

public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        if (context.Exception is JsonException jsonEx)
        {
            // 返回自定义格式的错误响应
            context.Result = new BadRequestObjectResult(new
            {
                status = 400,
                message = "参数格式错误",
                errors = new Dictionary<string, string[]>
                {
                    { "identification_guid", new[] { jsonEx.Message } }
                }
            });
            context.ExceptionHandled = true;
        }
        else
        {
            base.OnException(context);
        }
    }
}

方案二:通过模型验证处理(IValidatableObject)

这种方式先将Guid字段以字符串接收,再通过模型验证逻辑检查格式并转换,避免反序列化异常。

1. 修改User模型

public class User : IUserAccountBase, IValidatableObject
{
    [JsonPropertyName("identification_guid")]
    public string IdentificationGuidString { get; set; }
    
    [JsonIgnore] // 不参与JSON序列化/反序列化
    public Guid? IdentificationGuid { get; set; }
    
    [JsonPropertyName("first_name")]
    public string FirstName { get; set; }

    [JsonPropertyName("last_name")]
    public string LastName { get; set; }

    // 实现验证逻辑
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!string.IsNullOrWhiteSpace(IdentificationGuidString))
        {
            if (!Guid.TryParse(IdentificationGuidString, out Guid guid))
            {
                yield return new ValidationResult(
                    "identification_guid必须是有效的GUID格式",
                    new[] { nameof(IdentificationGuidString) });
            }
            else
            {
                // 验证通过后转换为Guid类型
                IdentificationGuid = guid;
            }
        }
    }
}

2. 在控制器中处理验证结果

[HttpPost("create-user")]
public async Task<IActionResult> CreateAsync([FromBody] User newUser)
{
    if (!ModelState.IsValid)
    {
        // 转换为自定义错误格式
        var errors = ModelState.ToDictionary(
            kvp => kvp.Key.Replace("IdentificationGuidString", "identification_guid"),
            kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray());
        
        return BadRequest(new
        {
            status = 400,
            message = "输入参数验证失败",
            errors = errors
        });
    }

    var result = user_service.CreateUser(newUser);
    return result;
}

方案三:重写ProblemDetailsFactory修改默认响应

这种方式无需修改模型或控制器,直接替换框架默认的错误响应生成逻辑,修改特定字段的错误信息。

1. 创建自定义ProblemDetailsFactory

public class CustomProblemDetailsFactory : ProblemDetailsFactory
{
    private readonly ApiBehaviorOptions _options;

    public CustomProblemDetailsFactory(IOptions<ApiBehaviorOptions> options)
    {
        _options = options.Value;
    }

    public override ValidationProblemDetails CreateValidationProblemDetails(
        HttpContext httpContext,
        ModelStateDictionary modelStateDictionary,
        int? statusCode = null,
        string title = null,
        string type = null,
        string detail = null,
        string instance = null)
    {
        var validationProblemDetails = base.CreateValidationProblemDetails(
            httpContext, modelStateDictionary, statusCode, title, type, detail, instance);

        // 替换Guid字段的错误信息
        if (validationProblemDetails.Errors.ContainsKey("$.identification_guid"))
        {
            validationProblemDetails.Errors["identification_guid"] = new[] { "identification_guid必须是有效的GUID格式" };
            validationProblemDetails.Errors.Remove("$.identification_guid");
            validationProblemDetails.Title = "参数验证失败";
        }

        return validationProblemDetails;
    }

    public override ProblemDetails CreateProblemDetails(
        HttpContext httpContext,
        int? statusCode = null,
        string title = null,
        string type = null,
        string detail = null,
        string instance = null)
    {
        var problemDetails = base.CreateProblemDetails(
            httpContext, statusCode, title, type, detail, instance);

        // 可根据需要修改其他错误响应
        return problemDetails;
    }
}

2. 注册自定义工厂

在Startup.cs的ConfigureServices方法中:

services.AddSingleton<ProblemDetailsFactory, CustomProblemDetailsFactory>();

以上三种方案都可以实现自定义错误信息的返回,你可以根据项目的实际情况选择合适的方式。

内容的提问来源于stack exchange,提问作者ks5485

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 06:54:25