能否将字符串列表绑定至ActionResult中Bind特性的Include属性?
答案:可以实现,但需利用常量字符串或编译时常量数组
好问题!你确实可以简化Bind(Include)里的长串属性列表,不过因为C#特性的参数必须是编译时常量,所以直接传递运行时的List<string>是不行的,但我们有更优雅的替代方案:
方法1:定义逗号分隔的常量字符串(最直接)
把所有需要Include的属性名用逗号拼接成一个const字符串,然后在Bind特性里引用它,这样既简洁又便于维护:
// 可以放在模型类内部或者单独的静态常量类中 public const string DataRequestEditInclude = "Property1,Property2,Property3,Property4,Property5,..."; // 替换成你的50个属性名 // 你的Action方法 public async Task<ActionResult> CreateAsync([Bind(Include = DataRequestEditInclude)] ComplexModel complexModel) { if (ModelState.IsValid) { await DocumentDbRepository<ComplexModel>.CreateItemAsync(complexModel); return RedirectToAction("Index"); } return View(complexModel); }
BindAttribute会自动把这个逗号分隔的字符串分割成字符串数组,效果和你直接写几十个字符串完全一样。
方法2:利用params数组简化(适合少量属性,50个还是建议用方法1)
如果不想用字符串常量,也可以直接在特性里用数组初始化器的语法(本质是利用params string[]参数),不过50个属性的话写起来还是很长:
public async Task<ActionResult> CreateAsync([Bind(Include = new[] { "Property1", "Property2", /* ... 其他48个 ... */ })] ComplexModel complexModel) { // 方法体不变 }
额外建议:避免魔法字符串(强类型优化)
如果想完全摆脱魔法字符串,防止属性名修改后出现错误,可以写一个简单的辅助工具类生成Include字符串(虽然不能直接在特性里用,但可以用来生成常量字符串):
public static class BindHelper { public static string GetPropertyNames<T>(params Expression<Func<T, object>>[] propertyExpressions) { return string.Join(",", propertyExpressions.Select(expr => { if (expr.Body is MemberExpression memberExpr) return memberExpr.Member.Name; var unaryExpr = expr.Body as UnaryExpression; return ((MemberExpression)unaryExpr.Operand).Member.Name; })); } }
然后你可以在编译前用这个工具生成常量字符串(或者在调试时验证属性名是否正确):
// 运行时验证属性名是否正确 var includeString = BindHelper.GetPropertyNames<ComplexModel>( m => m.Property1, m => m.Property2, // ... 其他属性 ... ); // 把输出结果复制到const字符串中即可
注意事项
- 一定要确保所有需要绑定的属性都在Include列表里,否则模型绑定会忽略这些属性;
- 使用
Bind(Include)是防止Mass Assignment攻击的有效手段,不要为了图省事省略白名单。
内容的提问来源于stack exchange,提问作者Carlos Lopez
相关产品推荐
相关产品推荐

