.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
相关产品推荐
相关产品推荐

