AJAX Pass Knockout ObservableArray and additional Parameter to MVC 4 Controller

3,088 views
Skip to first unread message

Omar...@ozkarservices.com

unread,
Jan 10, 2013, 4:23:17 PM1/10/13
to knock...@googlegroups.com
Hi Guys,

I trying to pass my Knockout Observable Array and two other Parameters. Section 1 is passing only the ObservableArray to my MVC 4 Controller and it working fine, I see the output in the debugger. Section 2 is passing the ObservableArray and 1 Parameter to my MVC 4 Controller and it fails with Error Code 500. Section 2 has more details on the error message

Begin Section 1

Here's my Ajax Call to my MVC Controller

                $.ajax({
                    url: 'Order',
                    type: 'POST',
                    contentType: 'application/json; charset=utf-8',
                    data: ko.toJSON(my.vm.Contact),
                    success: function (data) {
                        if (data.success == true) {
                            alert('Im done');
                        }
                    }
                });


Here's my MVC 4 Action

        [HttpPost]
        public JsonResult Order(List<PartyContacts> Contacts)
        {          
            return Json(new { success = true });
        }

EndSection 1



Begin Section 2

Here's my Ajax Call to my MVC Controller

                $.ajax({
                    url: 'Order',
                    type: 'POST',
                    contentType: 'application/json; charset=utf-8',
                    data: ko.toJSON(my.vm.Contact) + '&FirstName=hi',
                    success: function (data) {
                        if (data.success == true) {
                            alert('Im done');
                        }
                    }
                });

Here's my MVC 4 Action

        [HttpPost]
        public JsonResult Order(List<PartyContacts> Contacts, string FirstName)
        {          
            return Json(new { success = true });
        }



Error Message: Invalid JSON primitive: FirstName=hi.

JSON Data: [{"FullName":"Oscar Martinez","FirstName":"Oscar","LastName":"Martinez","Address":"","Apartment":"","City":"","State":"","PostalCode":"","HomePhone":"","WorkPhone":"","FaxNumber":"","EmailAddress":""}],FirstName=hi



EndSection 2



Can someone please tell me what I'm doing wrong?
       

Jeff Tchang

unread,
Jan 10, 2013, 4:59:28 PM1/10/13
to knock...@googlegroups.com
Your 500 error is probably because the server tries to decode the JSON
and fails.

This is not valid JSON!

[{"FullName":"Oscar
Martinez","FirstName":"Oscar","LastName":"Martinez","Address":"","Apartment":"","City":"","State":"","PostalCode":"","HomePhone":"","WorkPhone":"","FaxNumber":"","EmailAddress":""}],FirstName=hi

You basically concatenated a string to the end of your nice normal
looking JSON object.

In your case sometimes I like to add in the view model another observable:

function Contact() {
var self = this;
self.firstName = ko.observable();
}

Then do your thing:

my.vm.Contact.firstname("hi");

Then:

ko.toJSON(my.vm.Contact)


But lots of other ways to do it. I personally use the knockout mapping plugin!

-Jeff
> --
>
>

Omar...@ozkarservices.com

unread,
Jan 10, 2013, 5:03:39 PM1/10/13
to knock...@googlegroups.com, Omar...@ozkarservices.com
What if I format the string into a ko.JSON will it work? What other option do I have? Please provide me with an examples.

Thanks

Jeff Tchang

unread,
Jan 10, 2013, 5:06:59 PM1/10/13
to knock...@googlegroups.com
You can do:

foo = ko.toJS(my.vm.Contact);
foo['FirstName'] = 'hi';

then you can turn foo into JSON with whatever method you want.


ko.toJSON(foo);
> --
>
>

Omar...@ozkarservices.com

unread,
Jan 10, 2013, 6:05:03 PM1/10/13
to knock...@googlegroups.com, Omar...@ozkarservices.com
Jeff,

I don't want to confuse you. So let me explain how I invision the application to work. The client will have a Section where they will enter their company information and they I will provide them with another section on the same page where they could enter contact information related to the company. A company could have several different contacts and I will associated these contact to the company profile.

Below is my Contact model and you suggestion was to add another observable to the model. Would it make sense to add here or created another model?



    //Create Contact Model
    my.Contact = function (FullName, FirstName, LastName, Address, Apartment, City, State, PostalCode, HomePhone, WorkPhone, FaxNumber, EmailAddress) {
        this.FullName =  ko.observable(FullName),
        this.FirstName = ko.observable(FirstName),
        this.LastName =  ko.observable(LastName),
        this.Address = ko.observable(Address),
        this.Apartment = ko.observable(Apartment),
        this.City = ko.observable(City),
        this.State = ko.observable(State),
        this.PostalCode = ko.observable(PostalCode),
        this.HomePhone = ko.observable(HomePhone),
        this.WorkPhone = ko.observable(WorkPhone),
        this.FaxNumber = ko.observable(FaxNumber),
        this.EmailAddress = ko.observable(EmailAddress)
    };


    my.vm = {
        Contact: ko.observableArray([]),
        AddContact: function () {
            my.vm.Contact.push({
                FullName: $('#FirstName').val() + ' ' + $('#LastName').val(),
                FirstName: $('#FirstName').val(),
                LastName: $('#LastName').val(),
                Address: $('#Address').val(),
                Apartment: $('#Apartment').val(),
                City: $('#City').val(),
                State: 'NY',
                PostalCode: $('#PostalCode').val(),
                HomePhone: $('#HomePhone').val(),
                WorkPhone: $('#WorkPhone').val(),
                FaxNumber: $('#FaxNumber').val(),
                EmailAddress: $('#EmailAddress').val()
            });
        },
        DeleteContact: function (Contact) {
            my.vm.Contact.remove(Contact);
        }
       
    }

Thanks for your help!!


On Thursday, January 10, 2013 4:23:17 PM UTC-5, omar...@ozkarservices.com wrote:

Omar...@ozkarservices.com

unread,
Jan 11, 2013, 2:22:03 PM1/11/13
to knock...@googlegroups.com, Omar...@ozkarservices.com
Hi Jeff,
 
So I decided to write a different model for testing purpose. But I running into a issue when I try to extract the data in my MVC controller
 
 
Knockout Model
 
my.CompanyProfile = function (Profiles) {
  var self = this;
  self.Profiles = ko.observableArray(ko.utils.arrayMap(Profiles, function (Address) {
    return {
      FirstName: Address.firstName,
      LastName: Address.lastName,
      phones: ko.observableArray(Address.phones)
    };
  }));
};
my.vm = {
  Profile: ko.observableArray([]),
  AddProfile: function () {
    my.vm.Profile.push({

      FirstName: "Oscar",
      LastName: "Martinez",
      phones: ko.observableArray()
    });
  },
  AddProfilePhone: function (Profile) {
    Profile.phones.push({
      type: "1",
      number: "2"
    });
  },

}
ko.applyBindings(my.vm);
 
 
MVC Model
 

 public class PartyContacts
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Address { get; set; }
        public string Apartment { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
        public string HomePhone { get; set; }
        public string WorkPhone { get; set; }
        public string FaxNumber { get; set; }
        public string EmailAddress { get; set; }
        public List<string> phones { get; set; }
    }

 
Ajax Call and Convert to JSON
 
$.ajax({
  url: 'Order',
  type: 'POST',
  contentType: 'application/json; charset=utf-8',
  data: ko.toJSON(my.vm.Profile),

  success: function (data) {
    if (data.success == true) {
      alert('Im done');
    }
  }
});
 
 
MVC Controller Acction
 
[HttpPost]
public JsonResult PlaceOrder(List < PartyContacts > Contacts) {
  //var yourObject = JsonConvert.DeserializeObject(Contacts);
  return Json(new {
    success = true
  });
}
 
 
When I run this code I able to see the Knockout Model in the MVC Controller but for some reason my Phones ObservableArray does not come through. If inspect the data converted JSON I'm able to see the Phone ObservableArray. Below is the JSON results when I debug via Firebug.
 
Knockout Data Converted to JSON
 
"[{"FirstName":"Oscar","LastName":"Martinez","phones":[{"type":"1","number":"2"}]}]"
 
 
I think the issue is related to my property "Phones" on my class called PartyContact. What do you think?
 
public List<string> phones { get; set; }
 

On Thursday, January 10, 2013 4:23:17 PM UTC-5, omar...@ozkarservices.com wrote:

Jeff Tchang

unread,
Jan 11, 2013, 6:00:18 PM1/11/13
to knock...@googlegroups.com, Omar...@ozkarservices.com
I'm not too familiar with the backend language used (is it C#?) but it
looks like you are POSTing so at this point I would debug your backend
code.
> --
>
>

Omar...@ozkarservices.com

unread,
Jan 17, 2013, 3:46:11 PM1/17/13
to knock...@googlegroups.com, Omar...@ozkarservices.com
 
 
Jeff,
 
I figure out the problem. It was on my C# side. I'm going to post my solution in case anyone has the same issue I did.
Basically the issue was the I was trying to pass an array to a List<string> but it was failing because it was a 2 Dimensional Array not a Single Dimensional Array  , so to fix the problem I had to create a class for the Phone array and define the incoming array.
 
public class Order
    {
 public class OrderModel
    {

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Address { get; set; }
        public string Apartment { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
        public string HomePhone { get; set; }
        public string WorkPhone { get; set; }
        public string FaxNumber { get; set; }
        public string EmailAddress { get; set; }
        public List<PhoneModel> phones { get; set; }
    }
 
    public class PhoneModel
    {
        public string type { get; set; }
        public string number { get; set; }
    }
}

Ajax Call and Convert to JSON
 

$.ajax({
  url: 'Order',
  type: 'POST',
  contentType: 'application/json; charset=utf-8',
  data: ko.toJSON(my.vm.Profile),
  success: function (data) {
    if (data.success == true) {
      alert('Im done');
    }
  }
});
 
 
MVC Controller Acction
 
[HttpPost]
public JsonResult PlaceOrder(List < OrderModel > OrderModel) {

Omar...@ozkarservices.com

unread,
Jan 17, 2013, 4:17:51 PM1/17/13
to knock...@googlegroups.com, Omar...@ozkarservices.com
Jeff,
 
Why is that I get the following error when I try to call the function AddProfilePhone
 
0x800a138f - Microsoft JScript runtime error: Unable to get value of the property 'AddProfilePhone': object is null or undefined
 
If I fire this function AddProfile then it works.
 
This is the way I'm firing th event
 
$('#Add').live('click', function () {
AddProfilePhone();
 });
 
 

Here my Knockout Modal


    my.vm = {
        Profile: ko.observableArray([]),
        AddProfile: function () {
            my.vm.Profile.push({

                FirstName: "Oscar",
                LastName: "Martinez",

                phones: ko.observableArray()
            });
        },
        AddProfilePhone: function (Profile) {
            Profile.phones.push({
                type: "1",
                number: "2"
            });
        },

       
    }

 

 

On Thursday, January 10, 2013 4:23:17 PM UTC-5, omar...@ozkarservices.com wrote:
Reply all
Reply to author
Forward
0 new messages