\$\begingroup\$
\$\endgroup\$
5
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
MPelletier
8263 gold badges10 silver badges22 bronze badges
You must log in to answer this question.
Explore related questions
See similar questions with these tags.
lang-cs
IModelBinderProviderto get rid of the ModelBinder attribute. read more \$\endgroup\$