创建一个类型化的 ModelState.AddModelError()
Posted
技术标签:
【中文标题】创建一个类型化的 ModelState.AddModelError()【英文标题】:Creating a typed ModelState.AddModelError() 【发布时间】:2012-11-13 21:29:40 【问题描述】:在控制器中,我可以执行数据库查找等并添加一些与模型属性相关的错误消息:
public ActionResult CreateJob(CreateJobModel viewModel)
var call = FindCall(viewModel.CallNumber);
if (call == null)
ModelState.AddModelError("CallNumber", "Idiot User!");
我不喜欢 CallNumber 是一个字符串,理想情况下它应该直接引用 viewModel.CallNumber,如果我更改该属性的名称,它也应该更改。
我怎样才能做到这一点?
我想代码最终会是这样的,它需要一个属性访问表达式:
AddModelFieldError(() => viewModel.CallNumber, "Idiot User!");
但我不确定如何创建这样的方法,或者在它是需要错误消息的子/内部属性的情况下。
【问题讨论】:
【参考方案1】:我会编写自己的通用扩展方法:
public static class ModelStateDictionaryHelper
public static void AddModelError<TViewModel>(
this ModelStateDictionary me,
Expression<Func<TViewModel, object>> lambdaExpression, string error)
me.AddModelError(GetPropertyName(lambdaExpression), error);
private static string GetPropertyName(Expression lambdaExpression)
IList<string> list = new List<string>();
var e = lambdaExpression;
while (true)
switch (e.NodeType)
case ExpressionType.Lambda:
e = ((LambdaExpression)e).Body;
break;
case ExpressionType.MemberAccess:
var propertyInfo = ((MemberExpression)e).Member as PropertyInfo;
var prop = propertyInfo != null
? propertyInfo.Name
: null;
list.Add(prop);
var memberExpression = (MemberExpression)e;
if (memberExpression.Expression.NodeType != ExpressionType.Parameter)
var parameter = GetParameterExpression(memberExpression.Expression);
if (parameter != null)
e = Expression.Lambda(memberExpression.Expression, parameter);
break;
return string.Join(".", list.Reverse());
default:
return null;
private static ParameterExpression GetParameterExpression(Expression expression)
while (expression.NodeType == ExpressionType.MemberAccess)
expression = ((MemberExpression)expression).Expression;
return expression.NodeType == ExpressionType.Parameter ? (ParameterExpression)expression : null;
及用法:
ModelState.AddModelError<CreateJobModel>(x => x.CallNumber,
"some kind attention");
它看起来与您询问的版本有点不同,但我希望它是可以接受的替代方案。
【讨论】:
@Yorro:很高兴知道,当我提供这个答案时,我不知道ExpressionHelper.GetExpressionText
存在于 MVC 框架中。
@Yorro 不错。我在想肯定有这样的课程:)【参考方案2】:
从 C# 6 开始,您可以使用 nameof
运算符。
public ActionResult CreateJob(CreateJobModel viewModel)
var call = FindCall(viewModel.CallNumber);
if (call == null)
ModelState.AddModelError(nameof(CreateJobModel.CallNumber), "Idiot User!");
【讨论】:
它只适用于单一级别,即 nameof(CreateJobModel.CallNumber),但不适用于 nameof(CreateJobModel.CallNumber.Extension)。 如果可能(?),我建议将模型属性的所有错误添加到模型状态字典中的同一键 可以将所有错误添加到 string.Empty 键,但为什么要在所有情况下都这样做?每个属性的键对于正确的错误报告很有意义。如果你不是这种情况,你甚至不需要字典。只返回一个错误数组。 你能把多个错误加到一个真正的键上吗?如果是,那么我会将嵌套对象中的所有错误添加到该对象的键中。以上是关于创建一个类型化的 ModelState.AddModelError()的主要内容,如果未能解决你的问题,请参考以下文章
从它的类型创建一个 UIViewController 具体类