Your web app looks awesome on the iPad, until…

FranchiseBlast: Franchise Intranet on iPad You decide to save it to your home screen.

If you’re doing this with a web application you’ve developed, you probably want to make it appear a bit more like a native app,  so you’ll add two meta tags to make the experience nicer (add an app icon and remove the navigation bar). Remember: Safari caches these tags when creating the shortcut, so you will need to delete/recreate the shortcut to force it to refresh.

Everything will look fine, until you reload the web app on some other occasion: ASP.NET Ajax is now completely broken and many of your styles are missing. Simply put, an application that worked fine when you shut down your iPad minutes ago will be completely unusable. No amount of refreshing will solve the issue. Clearing Safari’s cache and using it outside of the home screen icon is the only workaround.

Gotcha: Safari uses different HTTP User-Agent strings depending on context!

The iPad (and iPhone/iPod Touch) don’t use the same HTTP User-Agent string when a website is accessed normally via the Safari application versus a webpage that was saved to the home screen (which still uses Safar internally). Here’s an example:

  • Normal Safari: Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2
  • Website as app: Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8J2
    ASP.NET doesn’t recognize the latter as being Safari – it recognizes it as a generic browser with no capabilities. As an example: Supports JavaScript? Nope.
    Add this hack to your base page to fix it. It makes ASP.NET think that anything based on AppleWebkit is a newer browser – a much better default setting (for most of us) than assuming the browser was created back in 1994.
       1:     protected void Page_PreInit(object sender, EventArgs e)
       2:      {
       3:          if (Request.UserAgent != null && Request.UserAgent.IndexOf("AppleWebKit", StringComparison.CurrentCultureIgnoreCase) > -1)
       4:          {
       5:              this.ClientTarget = "uplevel";
       6:          }
       7:      }

The long answer

On and off over the course of a month, I spent dozens of hours investigating this issue. In the end, the fix is trivial and updated *.browser files will probably be produced by Microsoft over the next months/years. However, I did learn a lot about how to debug a web-app on the iPad in the process, and thought I’d share a few lessons learned. I’ve kept them purposefully brief as you can easily find detailed answers on Google or StackOverflow.

Enable Safari’s Developer Debug Console

That’s how I figured out ASP.NET AJAX wasn’t loading properly. Was getting JavaScript errors that you normally get when ASP.NET Ajax is not properly configured in the web.config file.

  • On the iPad: Settings –> Safari –> Developer –> Debug Console (on)

Install Firebug Lite on your iPad

I frequently use Firebug on my desktop computer to analyse web pages. The lite version on the iPad helped me review the HTML/JavaScript in greater detail. Install this bookmarklet (found it painful to do) then install the FireBug Lite bookmarklet. More info here.

Setup an HTTP Proxy

This helped me get in-depth information about exactly what HTML/JavaScript was being served in response to which HTTP Headers. That’s how I realized certain scripts were not being included when the User-Agent changed.

  • As I develop on a Windows machine, I made it run through Fiddler on my desktop. Other options found here.
  • In Fiddler, Tools > Fiddler Options > Connections –> Allow Remote Computers To Connect. Restart Fiddler. (Not working? Check Windows Firewall.)
  • On the iPad: Settings –> Wi-Fi –> Click on the right arrow for your connection –> HTTP Proxy –> Manual –> Set Server and Port. 

Other limitations worth knowing about

As everyone knows, Flash doesn’t work on the iPad/iPhone/iPod. It doesn’t come as a surprise to use that we have to eliminate it from our app (not a big detail for us).

However, one gotcha that had not come to mind initially is that certain JavaScript functionality such as click&drag or drag&drop does not work on the iPad given the differences in gestures between a conventional computer and a tablet. That code needs to be rewritten.

Did you experience any issues you’d like to share?