odata.read return data = undefined in Firefox

May 24, 2013 at 7:09 AM
Hi
I am calling odata using MVC4 with entitysetcontroller and in firefox returned data is always undefined but in other browser it is working fine

OData.defaultHttpClient.enableJsonpCallback = true;
        DefaultHandler();
        OData.read(
                        {
                            requestUri: "http://xxxxxxxxxx/odata/Company",
                            enableJsonpCallback: false,                             
                            datatype: "json",
                            headers:
                             { 
                             'Access-Control-Allow-Origin': '*', 
                             'Access-Control-Allow-Methods': 'GET',
                             'Content-Type': 'application/json', 
                             'Accept': 'text/html'                                 
                             },
                            method: "GET"
                        },
                        successOdata,
                        errorOdata
                    );
successOdata = function (data, response) {
//here data is undefined in firefox but in other browser it is fine working fine in phonegap and other devices
};

Can anyone suggest where is an issue?
Coordinator
May 24, 2013 at 8:56 PM
Hi shyamvashista12,

In the code that you posted you set OData.defaultHttpClient.enableJsonpCallback = true; which is correct to solve the same-origin policy issue on the browsers,
but in the request:
                            OData.read(
                            {
                            requestUri: "http://xxxxxxxxxx/odata/Company",
                            enableJsonpCallback: false,                            
                            datatype: "json",
                            ......
you set the value of enableJsonpCallback: false which overrides the value in OData.defaultHttpClient.enableJsonpCallback, so FF will not be able to get the response as the request needs to have jsonp enabled.


Regards,
Hussein
May 27, 2013 at 6:57 AM
Hi Hussein
Thanks for reply
But When I am setting enableJsonpCallback: true, Call is not going to server, every time it is returning error message in response.
When overriding the enableJsonpCallback: false, Call is going to server and return data in response.
Even in other browser it is working fine with enableJsonpCallback: false with cross browses.

I am using DefaultHandler(); before sending request
function DefaultHandler() {
        var oldDefaultHandler = OData.defaultHandler;
        OData.defaultHandler = {
            accept: oldDefaultHandler.accept,
            read: function (response, context) {                
                var contentType = response.headers["Content-Type"];
                if (contentType && contentType.indexOf("text/html") === 0) {
                    response.data = response.body;
                } else {
                    oldDefaultHandler.read(response, context);
                }
            },
            write: function (request, context) {
                oldDefaultHandler.write(request, context);
            }
        };
    }  
Still not getting where what is wrong with FF 21?
Coordinator
May 28, 2013 at 5:45 PM
In order to understand the issue can you please answer these questions:
  • What version of DataJS are you using ?
  • Do you have the code for the service ? if so, is JsonP enabled in the service ?
  • Can you please post the request/response headers for the request ?
May 29, 2013 at 6:04 AM
Edited May 29, 2013 at 6:09 AM
Hi
I am using
datajs-1.1.1beta.js
Yes I have that code and JsonP is enabled in the service and also using crossbrowserhandler class
public class CrossBrowserHandler : DelegatingHandler
{ 
    const string Origin = "Origin";
    const string AccessControlRequestMethod = "Access-Control-Request-Method";
    const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
    const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
    const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
    const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {               
            bool isCorsRequest = request.Headers.Contains(Origin);
            bool isPreflightRequest = request.Method == HttpMethod.Options;
            if (isCorsRequest)
            {
                if (isPreflightRequest)
                {
                    return Task.Factory.StartNew<HttpResponseMessage>(() =>
                    {
                        HttpResponseMessage response = new HttpResponseMessage();
                        response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());

                        string accessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
                        if (accessControlRequestMethod != null)
                        {
                            response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod);
                        }

                        string requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
                        if (!string.IsNullOrEmpty(requestedHeaders))
                        {
                            response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
                        }

                        return response;
                    }, cancellationToken);
                }
                else
                {

                    return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(t =>
                    {
                        HttpResponseMessage resp = t.Result;
                        resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
                        return resp;
                    });
                }
            }
            else
            {
                return base.SendAsync(request, cancellationToken);
            }
        }
        catch (Exception ex)
        {

            return Task<HttpResponseMessage>.Factory.StartNew(() =>
            {
                return new HttpResponseMessage(HttpStatusCode.InternalServerError)
                {
                    Content = new StringContent("Error encountered in browser handling.")
                };
            });
        }
    }
} 

Request before Crossbrowser handing

{Method: OPTIONS, RequestUri: 'http://xxxxxxxxxxxxx/odata/Company?$top=10', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: keep-alive
Accept: text/html
Accept: application/xhtml+xml
Accept: application/xml; q=0.9
Accept: /; q=0.8
Accept-Encoding: gzip
Accept-Encoding: deflate
Accept-Language: en-us
Accept-Language: en; q=0.5
Host: xxxxxxxxxxxxxxxx
User-Agent: Mozilla/5.0
User-Agent: (Windows NT 6.1; rv:12.0)
User-Agent: Gecko/20100101
User-Agent: Firefox/12.0
Origin: http://xxxxxxxxxxxxx
Access-Control-Request-Method: GET
Access-Control-Request-Headers: access-control-allow-methods,access-control-allow-origin,authorization-token,content-type,maxdataserviceversion

}}

Request after Crossbrowser handing

{Method: GET, RequestUri: 'http://xxxxxxxxxxxxx/odata/Company?$top=10', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: keep-alive
Accept: text/html
Accept-Encoding: gzip
Accept-Encoding: deflate
Accept-Language: en-us
Accept-Language: en; q=0.5
Host: localhost:61575
Referer: http://xxxxxxxxxxx/WebApiClient/Test.aspx
User-Agent: Mozilla/5.0
User-Agent: (Windows NT 6.1; rv:12.0)
User-Agent: Gecko/20100101
User-Agent: Firefox/12.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Authorization-Token: 94,214,182,1,98,51,181,18,190,167,152,19
MaxDataServiceVersion: 1.0
Origin: http://xxxxxxxxxxxxxxx
Content-Type: application/json

}}

Response


{StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.ObjectContent1[[System.Linq.IQueryable1[[WebApi.Dto.CompDto, WebApi.Dto, Version=1.0.0.0, Culture=neutral,

PublicKeyToken=null]], System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Headers:
{
Access-Control-Allow-Origin: http://xxxxxxxxxx Content-Type: application/json; charset=utf-8 DataServiceVersion: 1.0
}}
Coordinator
May 30, 2013 at 9:15 PM
There are two things that happen here:

When setting enableJsonPCallback on the request,
the request should be something like
http://xxxxxxxxxxxxx/odata/Company?$top=10'?$callback=parent.handleJSONP_0&$format=json

and the response should start with
parent.handleJSONP_0({ [response data]})

Also In the headers you are setting MaxDataServiceVersion: 1.0, and this will not work, you need to set MaxDataServiceVersion to 3.0.

In order to know whether the problem is from Datajs or from the service, you can try your request in the browser and add this
"?$callback=parent.handleJSONP_0&$format=json" as query options in the request.
If the response is as expected and contains parent.handleJSONP_0({ [response data]}), then the service is fine and the problem is in the request datajs makes, other than that, the problem will be from the service support to Jsop

Can you try that and let me know the result ?