Search code examples
c#json.netodata

Odata Controller: How to convert Odata response to C# object at client


We have got a Odata response as below:

"{\r\n  \"@odata.context\":\"http://localhost/ApplicationService/model/$metadata#Edm.String\",\"value\":\"{\\\"Messages\\\":[\\\"message 1\\\",\\\"message 2\\\",\\\"message 3\\\",\\\"message 4\\\"],\\\"IsValidEntity\\\":false}\"\r\n}"

Now say we have a class:

    public class myValidationResult
    {
        public myValidationResult()
        {
            Messages = new List<string>();
        }
        public List<string> Messages { get; set; }
        public bool IsValidEntity { get; set; }
    }

This class used in MyOdataController class as below:

public class MyODataController : ODataController 
{
        [Authorize(Roles = "Admin")]
        public async Task<IHttpActionResult> Post(T entity)
        {
                myValidationResult  vResult = new myValidationResult();
                vResult.Messages.Add("message 1");
                vResult.Messages.Add("message 2");
                vResult.Messages.Add("message 3");
                vResult.Messages.Add("message 4");
                vResult.IsValidEntity = false;

                 var strResult = JsonConvert.SerializeObject(vResult);
                var resp = Content(HttpStatusCode.BadRequest, strResult );

                return resp;
        }
}

For the client Consuming this, we created below Class:

public class OData<T> 
{
    [JsonProperty("odata.context")]
    public string Metadata { get; set; }
    public T value { get; set; }
}

In the method where we call the Odata method & store response in 'msg':

var resp = msg.Result.Content.ReadAsStringAsync().Result;

resp is:

"{\r\n  \"@odata.context\":\"http://localhost/ApplicationService/model/$metadata#Edm.String\",\"value\":\"{\\\"Messages\\\":[\\\"message 1\\\",\\\"message 2\\\",\\\"message 3\\\",\\\"message 4\\\"],\\\"IsValidEntity\\\":false}\"\r\n}"


var odatares = JsonConvert.DeserializeObject<OData<myValidationResult>>(resp);

But the above line giving error:

Can not convert value\":\"{\\\"Messages\\\":[\\\"message 1\\\",\\\"message 2\\\",\\\"message 3\\\",\\\"message 4\\\"],\\\"IsValidEntity\\\":false}  to <.....namespace......>myValidationResult

Please suggest accordingly.


Solution

  • The OData response contains a string, not an instance of myValidationResult. Also, the response looks like it's missing some backslashes. (Are you sure the response shown is exactly what you received from the service?)

    You can either fix the serialization of myValidationResult on the service:

    // Don't serialize vResult yourself. OData will do it for you.
    var resp = Content(HttpStatusCode.BadRequest, vResult );
    

    Or deserialize in two steps as follows.

    var data = "{\r\n \"@odata.context\":\"http://localhost/ApplicationService/model/$metadata#Edm.String\",\"value\":\"{\\\"Messages\\\":[\\\"message 1\\\",\\\"message 2\\\",\\\"message 3\\\",\\\"message 4\\\"],\\\"IsValidEntity\\\":false}\"\r\n}";
    var outer = Newtonsoft.Json.JsonConvert.DeserializeObject<OData<string>>(data);
    var inner = Newtonsoft.Json.JsonConvert.DeserializeObject<myValidationResult>(outer.value);
    

    One more thing: The JsonProperty on OData<T> should be named @odata.context.