MVC 3 model binding with underscores
You can start writing a custom Json.NET ContractResolver
:
public class DeliminatorSeparatedPropertyNamesContractResolver : DefaultContractResolver{ private readonly string _separator; protected DeliminatorSeparatedPropertyNamesContractResolver(char separator) : base(true) { _separator = separator.ToString(); } protected override string ResolvePropertyName(string propertyName) { var parts = new List<string>(); var currentWord = new StringBuilder(); foreach (var c in propertyName) { if (char.IsUpper(c) && currentWord.Length > 0) { parts.Add(currentWord.ToString()); currentWord.Clear(); } currentWord.Append(char.ToLower(c)); } if (currentWord.Length > 0) { parts.Add(currentWord.ToString()); } return string.Join(_separator, parts.ToArray()); }}
This is for your particular case, becase you need a snake case ContractResolver
:
public class SnakeCasePropertyNamesContractResolver : DeliminatorSeparatedPropertyNamesContractResolver{ public SnakeCasePropertyNamesContractResolver() : base('_') { }}
Then you can write a custom attribute to decorate your controller actions:
public class JsonFilterAttribute : ActionFilterAttribute{ public string Parameter { get; set; } public Type JsonDataType { get; set; } public JsonSerializerSettings Settings { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext.HttpContext.Request.ContentType.Contains("application/json")) { string inputContent; using (var reader = new StreamReader(filterContext.HttpContext.Request.InputStream)) { inputContent = reader.ReadToEnd(); } var result = JsonConvert.DeserializeObject(inputContent, JsonDataType, Settings ?? new JsonSerializerSettings()); filterContext.ActionParameters[Parameter] = result; } }}
And finally:
[JsonFilter(Parameter = "model", JsonDataType = typeof(UserArgLevelModel), Settings = new JsonSerializerSettings { ContractResolver = new SnakeCasePropertyNamesContractResolver() })]public ActionResult UpdateArgLevel(UserArgLevelModel model) {{ // model is deserialized correctly!}