Friday, March 2, 2012

Binding, posting to a Dictionary in MVC 3 using jQuery ajax

This is a continuation of the previous two posts-
  1. Posting an array or generic list of string to asp.net MVC 3 using jQuery ajax
  2. Posting and binding generic list or array of complex object in MVC 3 using jQuery ajax
In this post we are going to discuss how to post data to a Dictionary using jQuery ajax. Lets have a simple model from the previous post and pass value to the action method as dictionary of the model we get the following controller method-
[HttpPost]
public ActionResult Binding_posting_to_a_dictionary_using_ajax(Dictionary<string, UserModel> userList)
{
    return PartialView("Success");
}
To work with dictionary the default model binder will accept the data in a particular format. If we consider key of the first element of the dictionary as firstkey then we have to give the name of the input parameter as [0].value.ModelPropertyName. So, for the first item we can give the names like-
<input name="[0].key" value="firstkey" type="hidden">
<input name="[0].value.FirstName" value="" type="text">
<input name="[0].value.LastName" value="" type="text">
<input name="[0].value.Age" value="" type="text">
If we see the above code block, we can see there is a hidden field for maintaining the key of the dictionary element and the value of the hidden filed is nothing but the key of the dictionary element.

Below is the code for posting to a dictionary from jQuery ajax-
<div class="data">
    <h4>
        First User</h4>
    <input type="hidden" name="[0].key" value="first" />
    First Name: @Html.TextBox("[0].value.FirstName")
    Last Name: @Html.TextBox("[0].value.LastName")
    Age: @Html.TextBox("[0].value.Age")
</div>
<div class="data">
    <h4>
        Second User</h4>
    <input type="hidden" name="[1].key" value="second" />
    First Name: @Html.TextBox("[1].value.FirstName")
    Last Name: @Html.TextBox("[1].value.LastName")
    Age: @Html.TextBox("[1].value.Age")
</div>
<div class="data">
    <h4>
        Third User</h4>
    <input type="hidden" name="[2].key" value="third" />
    First Name: @Html.TextBox("[2].value.FirstName")
    Last Name: @Html.TextBox("[2].value.LastName")
    Age: @Html.TextBox("[2].value.Age")
</div>
<input type="button" id="submitData" value="Submit data" />
<script type="text/javascript">
    $(document).ready(function () {
        $("#submitData").click(function () {
            var datatopost = new Object();
            $(".data").each(function (i, item) {
                datatopost[$(item).find("input[name*=FirstName]").attr("name")] = $(item).find("input[name*=FirstName]").val();
                datatopost[$(item).find("input[name*=LastName]").attr("name")] = $(item).find("input[name*=LastName]").val();
                datatopost[$(item).find("input[name*=Age]").attr("name")] = $(item).find("input[name*=Age]").val();
                datatopost[$(item).find("input[name*=key]").attr("name")] = $(item).find("input[name*=key]").val();
            });
            $.ajax({
                url: '@Url.Action("Binding_posting_to_a_dictionary_using_ajax")',
                type: 'POST',
                traditional: true,
                data: datatopost,
                dataType: "json",
                success: function (response) {
                    alert(response);
                },
                error: function (xhr) {
                    alert(xhr);

                }
            });
        });
    });
</script>
[HttpPost]
       [HttpPost]
        public JsonResult Binding_posting_to_a_dictionary_using_ajax(Dictionary<string, UserModel> userList)
        {
            return Json("Success");
        }
Explanation of the jQuery code is given in the previous post. We can check the input data of the ajax call and the posted value of dictionary data in the image below-

2 comments:

  1. thank you,
    it is exactly what I need.

    Did you try to submit two dictionaries? I did not find a way how to do it for MVC3

    ReplyDelete
    Replies
    1. Yes,

      You can do this by appending the variable name in the name declaration like below-

      Suppose you have the following controller action-
      [HttpPost]
      public ActionResult Binding_posting_to_a_dictionary_using_ajax(Dictionary userList, Dictionary anotherUser)
      {
      return PartialView("Success");
      }

      You can generate the HTML like-
      &ltinput name="userList[0].key" value="firstkey" type="hidden"&gt
      &ltinput name="userList[0].value.FirstName" value="" type="text"&gt
      &ltinput name="userList[0].value.LastName" value="" type="text"&gt
      &ltinput name="userList[0].value.Age" value="" type="text"&gt

      Check the image below-
      https://lh3.googleusercontent.com/-rJzJmTf4GC4/T_c4d9rQfHI/AAAAAAAAAUk/fjTo8JuL53U/s780/Binding%252C%2520posting%2520to%2520a%2520Dictionary%2520in%2520MVC%25203%2520using%2520jQuery%2520ajax%2520%25202.jpg

      Delete