If you are OK to go with 'dynamic' object parsing to your requirement (since you mentioned, you already tried changing Dictionary to dynamic), you may try with following approach.
Please note, though i am quite not sure if the approach fit your requirement but i hope it might help you in some way to start with.
I took the custom model binder(for specific property Type) approach since that's another extensibility point to deal with complex model/property binding in ASP.NET MVC
Custom Model Binder
public class ComplexObjectModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var contentType = controllerContext.HttpContext.Request.ContentType;
if (!contentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
return (null);
string jsonString;
using (var stream = controllerContext.HttpContext.Request.InputStream)
{
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream))
jsonString = reader.ReadToEnd();
}
if (string.IsNullOrEmpty(jsonString)) return (null);
DynamicComplexObject ExtraData = new DynamicComplexObject();
ExtraData.Details = new JavaScriptSerializer().Deserialize<dynamic>(jsonString);
return (ExtraData);
}
}
Register the custom binder in Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//Custom model binder registration
ModelBinders.Binders.Add(typeof(Models.DynamicComplexObject), new ComplexObjectModelBinder());
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
View Models:
public class ContentViewModel
{
public Guid Id { get; set; }
public int TypeId { get; set; }
public int FormId { get; set; }
public DynamicComplexObject ExtraData { get; set; }
}
//You may try to improve the following model and update the custom model binder logic as appropriate.
public class DynamicComplexObject
{
public dynamic Details { get; set; }
}
In following JSON i added one more level nesting for testing
var data = {
"Id": "",
"TypeId": "37",
"FormId": "",
"ExtraData": {
"title": "Some random title",
"contribute": "author",
"location": {
"url": "/Files/ed5cf2ea-c920.jpeg",
"size": "100",
"format": "application/json",
"onemorelocation": { //Added one more nested object to test
"a": 1,
"b": 2
}
}
}
};
$("#btnSubmit").on("click", function () {
$.ajax({
"datatype": "json",
"contentType": "application/json; charset=utf-8",
"type": "POST",
"url": '@Url.Action("SaveData", "Home")',
"data": JSON.stringify(data),
success: function (d) {
//Do stuff here
}
});
});
From debugging i can see the binding happening as shown in image.
