Umbraco SurfaceController无法接收非连续索引的列表项问题
ASP.NET模型绑定非连续索引列表的解决方案
问题本质
ASP.NET默认模型绑定对List<T>或数组的处理逻辑是从索引0开始连续匹配,一旦发现某个索引缺失(比如你提交时跳过了Extra[1]),就会终止对该列表后续项的绑定,导致Extra[2]这类非连续索引的项无法被接收。
可行解决方案
方案1:替换内层List为Dictionary
修改你的SMUKitPostViewModel,把内层的List<int>换成Dictionary<int, int>:
public class SMUKitPostViewModel { public Dictionary<string, Dictionary<int, int>> JerseyLayers { get; set; } }
模型绑定会自动将提交的<索引, 值>对映射到字典中,不管索引是否连续,所有提交的项都会被完整保留。你可以通过JerseyLayers["Extra"][2]直接访问对应的值,无需调整前端提交的字段名格式。
方案2:自定义模型绑定器
如果不想修改ViewModel结构,可以自定义一个针对List<int>的模型绑定器,强制处理非连续索引的提交项:
1. 实现自定义模型绑定器
public class NonContinuousListModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) throw new ArgumentNullException(nameof(bindingContext)); var prefix = bindingContext.ModelName + "["; var keys = bindingContext.ValueProvider.GetKeysFromPrefix(prefix); var list = new List<int>(); foreach (var key in keys) { if (int.TryParse(key.Replace(prefix, "").Replace("]", ""), out var index)) { var valueStr = bindingContext.ValueProvider.GetValue(key).FirstValue; if (int.TryParse(valueStr, out var value)) { // 若需保留索引位置,可填充空值到对应索引;若只需所有提交值,直接Add即可 while (list.Count <= index) list.Add(default); list[index] = value; } } } bindingContext.Result = ModelBindingResult.Success(list); return Task.CompletedTask; } }
2. 注册绑定器
可以全局注册,也可以在属性上单独标记:
- 全局注册(在Umbraco启动配置类中):
services.AddControllersWithViews(options => { options.ModelBinders.Insert(0, new NonContinuousListModelBinder()); });
- 属性级注册:
public class SMUKitPostViewModel { [ModelBinder(BinderType = typeof(NonContinuousListModelBinder))] public Dictionary<string, List<int>> JerseyLayers { get; set; } }
方案3:前端调整索引(可选)
如果前端逻辑可控,提交时将非连续索引重新整理为连续索引(比如把Extra[2]改为Extra[1]),就能让默认模型绑定正常接收所有项。但这种方法依赖前端修改,适合前端可调整的场景。
内容的提问来源于stack exchange,提问作者Jesse van Duijne
相关产品推荐
相关产品推荐

