"Invalid response for blob" Error When Making XHR Request

Whilst making a request to one of my API endpoints for an iOS application, I came across a very unhelpful error: "Invalid response for blob". I couldn't really understand why React Native was complaining about this single API endpoint, since all my other endpoints did not encounter this error.

React Native: Invalid Response For Blob

The API endpoint in question is a pretty simple email address validator. If the users email address is unique and passes all verification checks, the endpoint will either return a 200 (OK) or 400 (Bad Request) along with a response containing the error. For those who understand ASP.NET Web API development, my endpoint is as follows:

/// <summary>
/// Check if a user's email address is not already in user along with other string validation checks.
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
[Route("EmailAddressValidator")]
public HttpResponseMessage EmailAddressValidator(string email)
{
    if (UserLogic.IsEmailValid(email, out string error)) // UserLogic.IsEmailValid() method carries out email checks...
        return Request.CreateResponse(HttpStatusCode.OK);

    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorModel { Error = error });
}

So pretty simple stuff!

Weirdly enough the "Invalid response for blob" issue did not occur within my endpoint when the users email address did not pass the required checks, thus returning a 400 error and a response detailing the error. It was only when a 200 response was returned without a value.

There seems to be a bug in the React Native environment when it comes to dealing with empty API responses. The only way I could get around this, is to always ensure all my API endpoints returned some form of response. Very strange! I suggest all you fellow React Native developers do the same until a fix is put in place.

The issue has already been logged so I will be keeping an eye on a release for a fix.

Update (16/07/2018)

I wasn't too sure to whether anything had been done in regards to the fix since writing this post as there was no update to the Github issue that was first logged on the 5th March. So I decided to share this very post to a React Native group on Reddit to get some form of answer. Within a short period of time, I was told this issue has been fixed in React Native version 0.56.

Detecting Facebook In-App Browser

It seems there is going to be a growing trend where apps on our mobile devices will open webpages whilst you are inside the app itself instead of using the devices' native browser. A prime example of this is Facebook. In recent updates during the tail end of last year, both their iOS and Android offerings open webpages from within the application.

This isn't a bad thing. In fact I quite like having webpages opening within the application, since this creates a nice seamless experience. However, the Facebook in-app browser doesn't seem to render a webpage in the same manner as the devices' own native browser (Safari/Chrome). I started noticing this whilst working on a complex website that was very much custom JavaScript driven.

The only thing I could do is modify specific mark-up or features that affected my website negatively when opened from within Facebook by detecting the user-agent. In my code (using ASP.NET C#), I was required to carry out additional browser checks:

//User is within Facebook browser.
if (Request.UserAgent.IndexOf("FBAN") > -1)
{
    if (Request.UserAgent.Contains("iPhone OS 8_0_2"))
    {
        //You are using iPhone version 8.0.2.
    }
    
    if (Request.UserAgent.Contains("Chrome"))
    {
        //You are in the Facebook App in Android.
    }
}
else
{
    //You are not in Facebook App.
}

You can modify the code above to create a nice self-contained method to return an enumeration as I ended up doing to be used when required.

iOS Safari Browser Has A Massive Caching Issue!

Safari iOS6It wasn’t until today I found that the Safari browser used on iPad and iPhone caches page functionality to such an extent that it stops the intended functionality. So much so, it affects the user experience. I think Apple has gone a step too far in making their browser uber efficient to minimise page loading times.

We can accept browsers will cache style-sheets and client side scripts. But I never expected Safari to go as far as caching responses from web services. This is a big issue. So something as simple as the following will have issues in Safari:

// JavaScript function calling web service
function GetCustomerName(id)
{
    var name = "";

    $.ajax({
        type: "POST",
        url: "/Internal/ShopService.asmx/GetCustomerName",
        data: "{ 'id' : '" + id + "' }",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        cache: false,
        success: function (result) {
            var data = result.d;
            name = data;
        },
        error: function () {
        },
        complete: function () {
        }
    });
    
    return name;
}
//ASP.NET Web Service method
[WebMethod]
public string GetCustomerName(int id)
{
   return CustomerHelper.GetFullName(id);
}

In the past to ensure my jQuery AJAX requests were not cached, the “cache: false” option within the AJAX call normally sufficed. Not if you’re making POST web service requests. It’s only until recently I found using “cache:false” option will not have an affect on POST requests, as stated on jQuery API:

Pages fetched with POST are never cached, so the cache and ifModified options in jQuery.ajaxSetup() have no effect on these requests.

In addition to trying to fix the problem by using the jQuery AJAX cache option, I implemented practical techniques covered by the tutorial: How to stop caching with jQuery and JavaScript.

Luckily, I found an informative StackOverflow post by someone who experienced the exact same issue a few days ago. It looks like the exact same caching bug is still prevalent in Apple’s newest operating system, iOS6*. Well you didn’t expect Apple to fix important problems like these now would you (referring to Map’s fiasco!). The StackOverflow poster found a suitable workaround by passing a timestamp to the web service method being called, as so (modifying code above):

// JavaScript function calling web service with time stamp addition
function GetCustomerName(id)
{
    var timestamp = new Date();

    var name = "";

    $.ajax({
        type: "POST",
        url: "/Internal/ShopService.asmx/GetCustomerName",
        data: "{ 'id' : '" + id + "', 'timestamp' : '" + timestamp.getTime() + "' }", //Timestamp parameter added.
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        cache: false,
        success: function (result) {
            var data = result.d;
            name = data;
        },
        error: function () {
        },
        complete: function () {
        }
    });
    
    return name;
}
//ASP.NET Web Service method with time stamp parameter
[WebMethod]
public string GetCustomerName(int id, string timestamp)
{
    string iOSTime = timestamp;
    return CustomerHelper.GetFullName(id);
}

The timestamp parameter doesn’t need to do anything once passed to web service. This will ensure every call to the web service will never be cached.

*UPDATE: After further testing it looks like only iOS6 contains the AJAX caching bug.