0
\$\begingroup\$

I wrote this to have ASP.NET MVC be able to respond as a web API as well as the normal MVC Razor pages. I wanted Newtonsoft deserialization for models based on already parsed values:

public class CustomJsonModelBinder<T> : DefaultModelBinder
 where T : class
{
 public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
 {
 if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
 {
 return base.BindModel(controllerContext, bindingContext);
 }
 if (bindingContext.ModelType != typeof(T))
 {
 return base.BindModel(controllerContext, bindingContext);
 }
 //Get the DictionaryValueProvider, the one with all the JSON values already read
 if (!(bindingContext.ValueProvider is ValueProviderCollection valueProviders))
 {
 return base.BindModel(controllerContext, bindingContext);
 }
 DictionaryValueProvider<object> dictionaryValueProvider = valueProviders.FirstOrDefault(x => x.GetType() == typeof(DictionaryValueProvider<object>)) as DictionaryValueProvider<object>;
 if (dictionaryValueProvider == null)
 {
 return base.BindModel(controllerContext, bindingContext);
 }
 /* get the values and build a temp object for them for proper Newtonsoft Deserialization, which can have formatting attributes and others on the target class */
 Dictionary<string, object> valueDictionary = new Dictionary<string, object>();
 foreach (var entry in dictionaryValueProvider.GetKeysFromPrefix(""))
 {
 var value = bindingContext.ValueProvider.GetValue(entry.Key);
 valueDictionary.Add(entry.Key, value.RawValue);
 }
 string dictionaryInJson = JsonConvert.SerializeObject(valueDictionary);
 return string.IsNullOrEmpty(dictionaryInJson) ? base.BindModel(controllerContext, bindingContext) : JsonConvert.DeserializeObject<T>(dictionaryInJson);
 }
}

Usage:

public ActionResult Post(int id,[ModelBinder(typeof(CustomJsonModelBinder<AppointmentRequest>))] AppointmentRequest model)

I don't like having to repeat the model type twice, but I see no other convenient way.

Please let me know your thoughts!

asked Mar 11 at 14:14
\$\endgroup\$
5
  • \$\begingroup\$ implement IModelBinderProvider to get rid of the ModelBinder attribute. read more \$\endgroup\$ Commented Mar 13 at 11:48
  • \$\begingroup\$ Just curious why you chose NewtonSoft over the built-in? \$\endgroup\$ Commented May 8 at 19:30
  • \$\begingroup\$ @infinitezero First off, we ended up not going this route but instead using Web API 2.0 (with a "right tool for the right job" kinda-philosophy). My rationale was to use Newtonsoft instead of the built-in library which happens to be JavaScriptSerializer. It is not as customizable as Newtonsoft. \$\endgroup\$ Commented May 12 at 13:31
  • \$\begingroup\$ I don't know how it compares to Newtonsoft but the correct built-in is JsonSerializer. JavascriptSerializer is obsolete \$\endgroup\$ Commented May 12 at 14:26
  • \$\begingroup\$ @infinitezero Are you thinking of MVC Core? This was for MVC 5. \$\endgroup\$ Commented May 13 at 14:29

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.