Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebApi odata: Serialize long as string

I'm migrating form WCF Data Service to Web API odata v4. WCF Data Service did serilize long values in quotes:

{
   "value":[{
     "ID":"4527895973896126465"
   },{
     "ID":"4527895973896126466"
   }]
}

Web API odata does not:

{
   "value":[{
     "ID":4527895973896126465
   },{
     "ID":4527895973896126466
   }]
}

This means that I loose the precision of the 64bit number during JSON.parse in JavaScript, since JavaScript numbers are only 53bit.

Does WebApi has a build in mechanism to handle long values as string values? I'm thinking of the IEEE754Compatible header element. But this has no effect on the generated response. Am I overlooking something?

An alternative solution would be to deserilaize 64bit numbers as string values during JSON.parse on the client side. Is this possible?

like image 472
Jeldrik Avatar asked Oct 20 '22 12:10

Jeldrik


1 Answers

Finally I got this to work. OdataLib does indeed support this by the IEEE754Compatible parameter. It check's the response Content-Type header to see if the parameter is present.

The thing is, that the header value doesn't automatically get propageted to the response header by the web api framework. You have to do it on your own. I've build an ODataController derived class that patches the IEEE754Compatible parameter into the Content-Type header of the response like so:

public abstract class ODataControllerIEEE754Compatible : ODataController 
{
    private void PatchResponse(HttpResponseMessage responseMessage)
    {
        if (responseMessage != null && responseMessage.Content != null)
        {
           if (this.Request.Content.Headers.GetValues("Content-Type").Any(
               h => h.Contains("IEEE754Compatible=true")))
           {
               responseMessage.Content.Headers.TryAddWithoutValidation(
                  "Content-Type", "IEEE754Compatible=true");
           }
       }
    }

    public override Task<HttpResponseMessage> ExecuteAsync(
       HttpControllerContext controllerContext, CancellationToken cancellationToken)
    {
            var response = base.ExecuteAsync(
               controllerContext, cancellationToken);
            response.Wait(cancellationToken);

            PatchResponse(response.Result);

            return response;
    }
}

Now by sending the IEEE754Compatible=true parameter in the Content-Type Header I receive all long values serialized as JSON strings:

GET http://localhost/some/url HTTP/1.1
OData-Version: 4.0;
Content-Type: application/json;odata.metadata=minimal;IEEE754Compatible=true;charset=utf-8
Cache-Control: no-cache

HTTP/1.1 200 OK
Content-Type: application/json;odata.metadata=minimal;IEEE754Compatible=true
Server: Microsoft-HTTPAPI/2.0
OData-Version: 4.0

{
  "@odata.context":"http://localhost/some/url","value":[
{
  "ID":"4527895973896126465", ...
like image 109
Jeldrik Avatar answered Oct 28 '22 21:10

Jeldrik