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; } } } } }
On forkcan again…