Thursday, October 25, 2012

Knockoutjs ~ Int16 data mapping fails from JSON to .NET

We design class comprising of different data types based on our requirement. Assume there is a requirement to store the age of a person. In this case, we can specify any numerical datatype for Age like byte, short or int. In most cases we end up choosing int (Int32) datatype. But sometimes developer opts for either byte datatype or short (Int16) datatype.

Let’s assume that we have the following Person class with Age datatype as short (Int16).

public class Person
    {
        public Int32 Id { get; set; }
        public string Name { get; set; }
        public Int16 Age { get; set; }
    }

The corresponding class definition on the cshtml view (javascript side) will be defined as follows:

function Person (person) {
        var self = this;
        self.Id=ko.observable(person.Id);
        self.Name=ko.observable(person.Name);
        self.Age=ko.observable(person.Age);
    }

The following would normally be our method to send the information back to the server:

        self.save = function (person) {               
            $.ajax({
                type: "POST",
                url: "Save",
                data: ko.toJSON(self),
                dataType: 'json',
                contentType: 'application/json;charset=UTF-8',
                success: function (result) {
                    alert("success");
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    alert("save error status: " + xhr.status);
                    alert("save error thrown: " + thrownError);
                }
            });
        };

And the following would be our ASP.NET code to capture the information:

        [HttpPost]
        public JsonResult Save(Person person)
        {
            if (person == null) throw new ArgumentNullException("person");

            var personBusiness = new PersonBusiness();

            var result = person.Id == 0 ? personBusiness.Insert(person) : personBusiness.Update(person);

            return Json(result);
        }

In the above case we would expect that the person object would have the information mapped properly provided by the user but unfortunately Age will hold value of 0 no matter what value is supplied by the user. It seems like the mapping of short datatype is not properly implemented. This becomes evident when we change the datatype of Age from Int16 to Int32. Now on the save action we can see that the Age attribute will has the value as set by the user.

Hope this solves someone facing such issue.

No comments: