Gayan Ranasinghe Gayan Ranasinghe - 11 months ago 51
C# Question

Post data using jquery HybridDictionary as action parameter

i want to post data to action controller with this format

{
"key1" : "value1",
"key2" : "value2"
}


i want to map those values to
HybridDictionary
on my jquery post i use like this

$.ajax("/profile/post",
{
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ "key1": "value1", "key2": "value2" }),
method: "POST",
async: true,
success(e) { defer.resolve(e); },
error(e) { defer.reject(e); }
});


my action controller i get
Post(HybridDictionary data)
but seems it never gets posted values what was the wrong that i have done?

update

this is format I am getting those values

var c= new HybridDictionary();
c.Add("hello", "world");
c.Add("hello2", "world2");
c.Add("hello3", "world3");

Answer Source

There is nothing wrong with your ajax call. The problem is that you have no model binder setup to deserialize your json object on call execution. You can create a JsonModelBinder class in your App_Start folder and this code:

public class JsonModelBinder : DefaultModelBinder
{
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            if (!IsJsonRequest(controllerContext))
            {
                return base.BindModel(controllerContext, bindingContext);
            }

            // Get the JSON data that's been posted
            var request = controllerContext.HttpContext.Request;
            //in some setups there is something that already reads the input stream if content type = 'application/json', so seek to the begining
            request.InputStream.Seek(0, SeekOrigin.Begin);
            var jsonStringData = new StreamReader(request.InputStream).ReadToEnd();

            // Use the built-in serializer to do the work for us
            return new JavaScriptSerializer()
                .Deserialize(jsonStringData, bindingContext.ModelMetadata.ModelType);

            // -- REQUIRES .NET4
            // If you want to use the .NET4 version of this, change the target framework and uncomment the line below
            // and comment out the above return statement
            //return new JavaScriptSerializer().Deserialize(jsonStringData, bindingContext.ModelMetadata.ModelType);
        }

        private static bool IsJsonRequest(ControllerContext controllerContext)
        {
            var contentType = controllerContext.HttpContext.Request.ContentType;
            return contentType.Contains("application/json");
        }
}

    public static class JavaScriptSerializerExt
    {
        public static object Deserialize(this JavaScriptSerializer serializer, string input, Type objType)
        {
            var deserializerMethod = serializer.GetType().GetMethod("Deserialize", BindingFlags.NonPublic | BindingFlags.Static);

            // internal static method to do the work for us
            //Deserialize(this, input, null, this.RecursionLimit);

            return deserializerMethod.Invoke(serializer,
                new object[] { serializer, input, objType, serializer.RecursionLimit });
        }
    }

Then register it in your Global.asax.cs Application_Start method:

ModelBinders.Binders.DefaultBinder = new JsonModelBinder();