ASP.NET Core模型绑定验证IPAddress类型报错修复方案
问题根因
该异常和自定义JSON转换器无关,转换器仅负责请求/响应的JSON序列化、反序列化环节,不会介入模型绑定完成后的验证流程。
ASP.NET Core 默认模型验证管道会将所有未标记为简单类型的对象判定为复杂类型,递归遍历其所有公共属性执行校验。而System.Net.IPAddress类型的ScopeId属性仅支持IPv6地址实例访问,当绑定的是IPv4地址时,读取该属性会直接抛出SocketException,触发10045错误。
修复方案
最优方案是全局配置模型验证元数据,告知验证管道不要递归遍历IPAddress类型的内部属性,侵入性最低,不影响现有业务逻辑:
- 先实现针对IPAddress的验证元数据提供器:
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; using System.Net; public sealed class IPAddressValidationMetadataProvider : IValidationMetadataProvider { public void CreateValidationMetadata(ValidationMetadataProviderContext context) { if (context.Key.ModelType == typeof(IPAddress)) { // 关闭IPAddress类型的子属性递归验证 context.ValidationMetadata.ValidateChildren = false; } } }
- 在Program.cs的服务配置阶段注册该提供器,同时保留之前注册的IPAddress JSON转换器即可:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers() .AddJsonOptions(options => { // 保留原有自定义JSON转换器配置 options.JsonSerializerOptions.Converters.Add(new IPAddressConverter()); }) .AddMvcOptions(options => { // 注册自定义验证元数据提供器 options.ModelMetadataDetailsProviders.Add(new IPAddressValidationMetadataProvider()); }); // 其余启动配置保持原有逻辑即可
其他可选方案
如果不想做全局配置,也可以在每个用到IPAddress的DTO属性上标注特性,关闭对应属性的子级验证:
public class TestDto { public TestDto(IPAddress property) { Property = property; } // 标注特性,告知验证管道不要遍历该属性实例的内部属性 [ValidateNever(ValidateChildren = false)] public IPAddress Property { get; } }
该方案需要在所有用到IPAddress的属性上手动加标注,漏加就会复现异常,更推荐全局配置方案。
不要尝试通过捕获IPAddress属性访问异常的方式修复,该行为是系统类型的设计逻辑,强行修改会引入不必要的性能开销和版本兼容问题。
内容的提问来源于stack exchange,提问作者Nodon
相关产品推荐
相关产品推荐

