Sponsored

Thursday, January 29, 2009

ASP.NET AJAX Compatibility Patch for Safari 3.x and Google Chrome

The problem I am going to talk about is not new but it somehow managed to concern not so many developers so far. However, it is a growing concern and more people would need a solution at some point.

The heart of the problem is there are two browsers with a growing number of users - Safari 3.x and Google Chrome, that ASP.NET AJAX framework is not compatible with.

One part of the problem is induced by a fact that both browsers report themselves as "Webkit" which is not supported by ASP.NET AJAX. This part of the problem affects both Safari and Chrome users.

The second part of the problem mostly affects Safari users because ASP.NET AJAX framework does "support" Safari (version 2.x) but in such a manner that makes your web application look like a total disaster in Safari version 3.x.

The suggested fix will help both cases. At least my tests showed quite a success. Ideally we would need an official patch from Microsoft but since they have their own plans and busy with the next .NET/ASP.NET 4.0 and VS 2010 I would assume that there will be no fix till those versions are out.

So let's stick to this solution for now. The solutions for the problem were suggested by a couple of people: http://forums.asp.net/p/1252014/2898429.aspx and http://blog.lavablast.com/post/2008/10/Gotcha-WebKit-(Safari-3-and-Google-Chrome)-Bug-with-ASPNET-AJAX.aspx. Since both solutions are absolutely the same I want to give both of them a credit.  
Now to the point, ASP.NET AJAX framework has a class Sys.Browser that represents a current browser and supports cross-browser compatibility for everything else. The solution simply extends the Sys.Browser class to support a Webkitbrowser:

Sys.Browser.WebKit = {};
if( navigator.userAgent.indexOf('WebKit/') > -1 )  {
    Sys.Browser.agent = Sys.Browser.WebKit;
    Sys.Browser.version = parseFloat(navigator.userAgent.match(/WebKit\/(\d+(\.\d+)?)/)[1]);
    Sys.Browser.name = 'WebKit';
}
That is all the code you need. To apply this code to your web application you will need to create a JavaScript file, let's say webkit.js and reference it in your application using standard ScriptManager server control. You can reference the fix as a file using this syntax:

<asp:ScriptManager ID="sm" runat="server">
    <Scripts>
        <asp:ScriptReference Path="~/Scripts/webkit.js" />
    </Scripts>
</asp:ScriptManager>
or embed it into an assembly (my preferred way) and reference it from the assembly as an embedded resource:

<asp:ScriptManager ID="sm" runat="server">
    <Scripts>
        <asp:ScriptReference Assembly="Scripts" Name="Scripts.webkit.js" />
    </Scripts>
</asp:ScriptManager>
Note that when you reference the fix from an assembly don't forget to add an assembly default namespace to the file name in the Nameattribute. In conclusion, according to my tests the fix eliminated problems with UpdatePanel, AjaxControlToolkitand Virtual Earth map control.

14 comments:

  1. Doesnt seem to work for me.

    I have PageMethods, History enabled, Globalization enabled + ajax toolkit and jquery.

    I tested the script insertion and it was modified to Webkit (as per the Sys.Browse.Name.

    My calling control is a dropdownlist on autopostback.

    ReplyDelete
  2. Wow - I can't believe how long I looked for a solution to my issue (virtual earth map icons not showing up in Safari when I load the map with Ajax). Thanks a million for posting this great info!

    ReplyDelete
  3. To KnaveT:
    Could you clarify what exactly does not work for you? The best way to understand what's going on on the page is to look for a JavaScript error on your page.

    Also I don't exactly understand how a DropdownList with the AutoPostback is related to ASP.NET AJAX. Only if there is a JavaScript error on the page the AutoPostback would not work.

    ReplyDelete
  4. Fixed my problem! Thanks so much!

    ReplyDelete
  5. I already have a ScriptManager in my page, so I get the error "cannot have a duplicate ScriptManager"

    What I am doing wrong?

    ReplyDelete
  6. To Terry: you can't have two declarations of the ScriptManager on the page. You need to modify the existing declaration to add a fix script rather than add another declaration.

    ReplyDelete
  7. hi
    i am using safari 4.0.5, still i have the problem even after using the scripts you gave. I am using Master pages in my web application. It loads only the master page but not the contents of the page. Is there any separate script for master page scenario.
    But working fine with all other browsers. Please help me its very urgent!

    Thanks in Advance!

    ReplyDelete
  8. To Mukund The Lion: I don't exactly understand what's not working for you in Safari. I have tested this solution for all the Safari browsers including the latest version 5 and it's working for me. It has nothing to do with the master/content separation however the script of course should be referenced on the very first master page.

    ReplyDelete
  9. Hi,

    I already have telerik scriptmanager on my page. how do i add the fix script?

    ReplyDelete
  10. Awesome! thank you. The script allowed my Modal Popup Extender to work on Safari 5.0 (and the iPad).

    ReplyDelete
  11. Poor solution. If you actually look at the code that is in the Browser.js file you'll find that if you use this "HACK" it causes a breaking change elsewhere in the dll's. If you use any other controls in the AjaxToolKit I would highly recommend NOT using this hack and instead look a little deeper at the code.

    ReplyDelete
  12. To arsnic: I agree that this is a hack however it was introduced at the time when it was the only viable solution. Currently other solutions should also be available.

    ReplyDelete
  13. I believe I have found better solution than one posted above. I also found that with solution posted above, I was getting funky page refreshes in Chrome.

    My solution is to actually put code (that describes required functionality) in a trigger event associated with the dropdown that is inside the asp.net update panel. I found that the asp.net 'onSelectedIndexChange' code behind trigger event does indeed fire even inside of an asp.net update panel. I also found that what doesn't fire in Chrome and does fire in internet explorer is the JQuery document.ready function. Therefore my fix for chrome was to put the javascript I wrote inside the document.ready query function and copied it to the OnSelectedIndexChange .NET code behind event.

    ReplyDelete