ASP.NET Core自定义模型绑定类型转换报InvalidCastException问题
问题根因
抛出System.InvalidCastException: Object must implement IConvertible的核心原因有两个:
valueProvider.GetValue(key)返回的是ValueProviderResult类型的结构体,不是请求里的原始字符串值。代码没有取FirstValue拿到实际的参数内容,直接把整个ValueProviderResult实例传给了类型转换器,而ValueProviderResult没有实现IConvertible接口,转换器无法处理这种类型的输入。- 类型转换方法用错:
ConvertTo方法的作用是将传入的第一个参数对象转换为第二个参数指定的类型,当前场景需要把字符串格式的参数值转成目标类型T,应该用ConvertFrom/ConvertFromInvariantString方法,而不是ConvertTo。
另外代码还有一个隐藏问题:DataSourceRequestUrlParameters的所有静态属性没有初始化默认值,默认都是null,即使转换逻辑修好,也会因为键名不匹配拿不到URL里的page/pageSize/filter参数。
修复方案
- 修改
TryGetValue方法,先从ValueProviderResult中提取原始字符串值,再用正确的转换方法做类型转换,增加容错处理:
private static void TryGetValue<T>(ModelMetadata modelMetadata, IValueProvider valueProvider, string modelName, string key, Action<T> action) { if (modelMetadata.BinderModelName.HasValue()) { key = modelName + "-" + key; } var valueResult = valueProvider.GetValue(key); string rawValue = valueResult.FirstValue; if (string.IsNullOrWhiteSpace(rawValue)) { return; } try { var typeConverter = TypeDescriptor.GetConverter(typeof(T)); // 用不变文化转换URL参数,避免服务器区域格式差异导致数值、日期类型转换失败 var convertedValue = (T)typeConverter.ConvertFromInvariantString(rawValue); if (convertedValue != null) { action(convertedValue); } } catch { // 转换失败时对应参数保留默认值即可,可按需添加日志记录 } }
- 给
DataSourceRequestUrlParameters添加静态构造函数,初始化默认的Query参数名,保证和请求URL里的键名匹配:
public static class DataSourceRequestUrlParameters { static DataSourceRequestUrlParameters() { Page = "page"; PageSize = "pageSize"; Filter = "filter"; Sort = "sort"; Group = "group"; Aggregates = "aggregates"; Mode = "mode"; } public static string Aggregates { get; set; } public static string Filter { get; set; } public static string Page { get; set; } public static string PageSize { get; set; } public static string Sort { get; set; } public static string Group { get; set; } public static string Mode { get; set; } public static IDictionary<string, string> ToDictionary(string prefix); }
修改完成后,模型绑定器即可正常解析示例请求中的分页、过滤参数。
内容的提问来源于stack exchange,提问作者User_4373
相关产品推荐
相关产品推荐

