Skip to content

Instantly share code, notes, and snippets.

@Jaecen
Created January 4, 2017 01:15
Show Gist options
  • Save Jaecen/2d122faf93859e4e4eed2f3d2810d236 to your computer and use it in GitHub Desktop.
Save Jaecen/2d122faf93859e4e4eed2f3d2810d236 to your computer and use it in GitHub Desktop.
Maps ModelState values onto a property indicated by a lambda. Used to merge ModelStates from one model to another (i.e. PostModel to RenderModel). Usage: `ModelState.Apply(otherModel, m => m.SomeProperty)`
public static class ModelStateDictionaryExtensions
{
public static TValue Apply<TSource, TValue>(this ModelStateDictionary modelState, TSource source, Expression<Func<TSource, TValue>> selectorExpression)
{
// Extract property info from the selector expression
var memberExpression = selectorExpression.Body as MemberExpression;
if(memberExpression == null)
throw new ArgumentException($"Expression '{selectorExpression}' does not refer to a property", nameof(selectorExpression));
var propertyInfo = memberExpression.Member as PropertyInfo;
if(propertyInfo == null)
throw new ArgumentException($"Expression '{selectorExpression}' does not refer to a property", nameof(selectorExpression));
// Check if the model state contains the property
var sourceValueAccessor = selectorExpression.Compile();
if(!modelState.ContainsKey(propertyInfo.Name))
return sourceValueAccessor(source);
// Attempt to convert the model state value to the property type
try
{
return (TValue)modelState[propertyInfo.Name].Value.ConvertTo(typeof(TValue));
}
catch(InvalidOperationException)
{
return sourceValueAccessor(source);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment