Adding errors to the model state the typed way
Ah… there is one left. We do not only want to remove properties form the model state the typed way. What about adding error messages?
Here we go:
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Web.Mvc;
namespace devcoach.Web.Mvc
{
/// <summary>
/// Extensions for the <see cref="ModelStateDictionary"/> class.
/// </summary>
public static class ModelStateDictionaryExtensions
{
/// <summary>
/// Removes the specified member from the <see cref="ModelStateDictionary"/>.
/// </summary>
/// <param name="me">Me.</param>
/// <param name="lambdaExpression">The lambda expression.</param>
public static void Remove<TViewModel>(
this ModelStateDictionary me,
Expression<Func<TViewModel, object>> lambdaExpression)
{
me.Remove(GetPropertyName(lambdaExpression));
}
/// <summary>
/// Adds the model error.
/// </summary>
/// <typeparam name="TViewModel">The type of the view model.</typeparam>
/// <param name="me">Me.</param>
/// <param name="lambdaExpression">The lambda expression.</param>
/// <param name="errorMessage">The error message.</param>
public static void AddModelError<TViewModel>(
this ModelStateDictionary me,
Expression<Func<TViewModel, object>> lambdaExpression,
string errorMessage)
{
me.AddModelError(GetPropertyName(lambdaExpression), errorMessage);
}
/// <summary>
/// Adds the model error.
/// </summary>
/// <typeparam name="TViewModel">The type of the view model.</typeparam>
/// <param name="me">Me.</param>
/// <param name="lambdaExpression">The lambda expression.</param>
/// <param name="exception">The exception.</param>
public static void AddModelError<TViewModel>(
this ModelStateDictionary me,
Expression<Func<TViewModel, object>> lambdaExpression,
Exception exception)
{
me.AddModelError(GetPropertyName(lambdaExpression), exception);
}
/// <summary>
/// Gets the name of the property.
/// </summary>
/// <param name="lambdaExpression">The lambda expression.</param>
/// <returns></returns>
private static string GetPropertyName(this Expression lambdaExpression)
{
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;
return propertyInfo != null
? propertyInfo.Name
: null;
case ExpressionType.Convert:
e = ((UnaryExpression)e).Operand;
break;
default:
return null;
}
}
}
}
}