5

コントローラーでは、DB ルックアップなどを実行し、モデル プロパティに関連付けられたエラー メッセージを追加できます。

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!");

しかし、そのようなメソッドを作成する方法、またはエラーメッセージが必要なサブ/内部プロパティの場合はわかりません。

4

2 に答える 2

9

独自の汎用拡張メソッドを作成します。

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");

あなたが尋ねたバージョンとは少し異なって見えますが、それが受け入れられる代替手段になることを願っています.

于 2012-11-26T12:24:30.277 に答える
4

nameofC# 6 以降では、演算子を使用できます。

public ActionResult CreateJob(CreateJobModel viewModel)
{
    var call = FindCall(viewModel.CallNumber);

    if (call == null)
    {
        ModelState.AddModelError(nameof(CreateJobModel.CallNumber), "Idiot User!");
    }
}
于 2016-12-07T09:00:06.503 に答える