How OData.request can work with properties represented by a deffered property ?

Jan 3, 2014 at 12:15 AM
Hi, I have developed an application with VS2012 using Web API and OData.
The client is a SPA HTML page with Javascript, JQuery, JSViews and DataJS.

The web page receives objects with this command: 'OData.read( _url, _callback, _callback);'
The object contains links to properties that are composed of collections of objects, one Id and two strings.

I want to update the Comment property which is a string but if I provide the complete object the call fails.
If I create a temporary object with only the three properties, it works.

To perform my call, I use this command:
    OData.request(
        request,
        function (x, y, z) {
            var s = "success";
        },
        function (x, y, z) {
            var s = "failure";
        }
    );
The request object is:
    request = {
        requestUri: _url,
        method: "PUT",
        data: app
    };
Here is the definition of the two different 'app' objects I am using for tests :
    var app = {
        "Id":1,
        "Name":"MyInventory5",
        "Comment":"Test 1 for 1: MyInventory5"
    }
or
    var app = {
        "__metadata":{
            "type":"MyInventory2013.Models.Application",
            "properties":{
                "Id":{"type":null},
                "Name":{"type":null},
                "Comment":{"type":null},
                "ApplicationContacts":{"type":null},
                "ApplicationDivisions":{"type":null},
                "Configs":{"type":null},
                "Dependancies":{"type":null},
                "Dependancies1":{"type":null}
            },
            "id":"http://localhost:55431/odata/Applications(1)"
        },
        "Id":1,
        "Name":"MyApp",
        "Comment":"Comment for 1: MyApp",
        "ApplicationContacts":{
            "__deferred":{"uri":"http://localhost:55431/odata/Applications(1)/ApplicationContacts"}
        }
    }
On server side, this C# function is called :
    protected override T UpdateEntity(int key, T update)
Using the small "app" sample, the "update" object is of the right type and the properties are ok
but I'd prefer to receive the object from the service, update its Comment property and send it back for the update.

Using the large "app" sample, the "update" object is NULL on the server but I am able to find it using this code :
    if (update == null) {
        if (HttpContext.Current.Request.InputStream.CanSeek) {
            HttpContext.Current.Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);

            using (System.IO.StreamReader reader = new System.IO.StreamReader(HttpContext.Current.Request.InputStream)) {
                string content = reader.ReadToEnd();
                update = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(content);
            }
        }
    }
But, the DeserializeObject throws :
{
    "Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) 
    into type 'System.Collections.Generic.ICollection`1[MyInventory2013.Models.ApplicationContact]' 
    because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. 
    To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) 
    or change the deserialized type so that it is a normal .NET type 
    (e.g. not a primitive type like integer, not a collection type like an array or List<T>) 
    that can be deserialized from a JSON object. 
    JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. 
    Path 'ApplicationContacts.__deferred'"
}
I understand that it can't deserialize this property as it is not an array as expected but
I don't understand why it returns me data that I can't use for updates.

Could you please help me to find the correct way to deal with this ?

Thank you,
Claude