Skip to content

Instantly share code, notes, and snippets.

@dagstuan
Created August 17, 2017 10:40
Show Gist options
  • Save dagstuan/bfbed27cb37960142ff219a203f81f99 to your computer and use it in GitHub Desktop.
Save dagstuan/bfbed27cb37960142ff219a203f81f99 to your computer and use it in GitHub Desktop.
Validate model state and unflatten for use with redux-form.
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Http.ModelBinding;
using CDNAdmin.Web.Exceptions;
namespace CDNAdmin.Web.Filters
{
public class ValidateApiModelStateFilter : ActionFilterAttribute
{
private static readonly Regex ListElemRegex = new Regex(@"([a-zA-z]*)\[([^\[\]]*)\]");
private static T GetKeyFromDict<T>(string key, IDictionary<string, object> dict) where T : class, new()
{
if (!dict.ContainsKey(key))
{
dict[key] = new T();
}
return dict[key] as T;
}
private static void InsertListElem(Match listKeyMatch, IDictionary<string, object> dict, object objToInsert)
{
var key = listKeyMatch.Groups[1].Value;
var index = int.Parse(listKeyMatch.Groups[2].Value);
var list = GetKeyFromDict<List<dynamic>>(key, dict);
if (list.Count < index)
{
for (var i = list.Count; i < index; i++)
{
list.Add(null);
}
}
list.Insert(index, objToInsert);
}
private static void SetDictionaryElem(IList<string> keyList, IDictionary<string, object> dict, IList<string> errList)
{
var firstKey = keyList[0];
var listKeyMatch = ListElemRegex.Match(firstKey);
if (keyList.Count == 1)
{
if (string.IsNullOrWhiteSpace(firstKey)) return;
if (listKeyMatch.Success)
{
InsertListElem(listKeyMatch, dict, errList);
}
else
{
dict[firstKey] = errList;
}
}
else
{
if (listKeyMatch.Success)
{
var newDictElem = new Dictionary<string, object>();
InsertListElem(listKeyMatch, dict, newDictElem);
SetDictionaryElem(keyList.Skip(1).ToList(), newDictElem, errList);
}
else
{
var elem = GetKeyFromDict<Dictionary<string, object>>(firstKey, dict);
SetDictionaryElem(keyList.Skip(1).ToList(), elem, errList);
}
}
}
public static IDictionary<string, object> UnflattenModelState(ModelStateDictionary modelState)
{
var unflattenedModelState = new ExpandoObject() as IDictionary<string, object>;
foreach (var pair in modelState)
{
if (pair.Value.Errors.Count > 0)
{
var keySplit = pair.Key.Split('.').ToList();
var errors = pair.Value.Errors.Select(error => error.ErrorMessage).ToList();
SetDictionaryElem(keySplit, unflattenedModelState, errors);
}
}
return unflattenedModelState;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
var modelState = actionContext.ModelState;
if (!modelState.IsValid)
{
throw new ModelStateValidationException(UnflattenModelState(modelState));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment