Joshua Johnson

ASP.NET, ASP.NET AJAX, Silverlight, VS 2008

How do I overcome the dreaded Safari (and Chrome) / ASP.NET Menu conundrum?

UPDATE
Since I initially wrote this post, I found another way of solving the Safari / Chrome ASP.NET menu issue.
First, determine whether the user agent string contains "AppleWebKit". If so, set the Page.ClientTarget property to "uplevel".

    protected void Page_PreInit(object sender, EventArgs e)
    {
        if (Request.UserAgent != null && Request.UserAgent.IndexOf("AppleWebKit", StringComparer.CurrentCultureIgnoreCase) > -1)
        {
            this.ClientTarget = "uplevel";
        }
    }

NOTE: I have found from personal experience that the Request.UserAgent property in some cases might not be set. It is best practice to ensure that the user agent string is not null before calling the string's IndexOf method, otherwise, the code will throw a null reference exception.
Typically, you will not want to handle this event on every page that you have the ASP.NET menu, unless you have a tiny website.
Set the pageBaseType in the Web.config file to a class that inherits from System.Web.UI.Page and contains the above code.

      <configuration>
         <system.web>
            <pages pageBaseType="MyPageBase">
               ...
            </pages>
         </system.web>
      </configuration>

Here is another blog post on the menu problem.

Overview

Primarily, I develop external facing commercial Web sites. In this setting, I cannot dictate which Web browser will be used by the masses, so I have to proactively ensure that the layout and functionality remain either the same or gracefully degraded.

This can be a challenge when Internet Explorer 5/6/7, Mozilla Firefox, Apple Safari, and Opera Web browsers might adhere to differing standards.

Problem 

I found an article that describes a situation with the Apple Safari browser wherein ASP.NET renders the ASP.NET Menu control in a downgraded (not gracefully either) state. I have seen this issue a couple of times in the past several years and I thought it was worth mentioning.

Solution 

I will not go into much detail here, but in brief, in the %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers\mozilla.browser file, remove the Menu adapter reference from the Safari configuration, save the file, and then run the aspnet_regbrowsers.exe -i tool. Running that tool parses and compiles all system-wide browser definitions into an assembly and installs the assembly into the GAC.

Conclusion 

Typically, if only administering a single Web site, the preferable approach would be to create an App_Browsers folder in the root of the Web site and create a .browser file in that folder. Add the appropriate browser overrides in the file and you are good to go. No need to run an external tool. The browser configuration is dynamically compiled when the application starts. This is the only approach if the Web site is in a hosted environment.

In some future post, I would like to dive into a discussion of what are the major headaches that developers face when attacking browser compatibility issues and how to elegantly circumvent the browsers' woes.

What are the three or four issues that you find most irritating when developing for various browsers?

Hope this helps!

Joshua

Posted: Jan 23 2008, 11:11 PM by JoshuaJohnson | with 21 comment(s)
Filed under:

Comments

Walter Gameiro said:

Hi Joshua.

Great tip.

You can also achieve this on an individual web app basis by putting the following code in the Page_Load event of your Master pages:

if (Request.UserAgent.IndexOf("AppleWebKit") > 0)

       {

           Request.Browser.Adapters.Clear();

       }

# September 9, 2008 9:43 PM

Steve said:

Hi Guys,

Thankyou!!! That solved my problem!  

Josh, your little 3 lines of code code worked like a charm.

# October 14, 2008 1:26 AM

Siter said:

THANKS. This is of great help !

# December 25, 2008 11:35 AM

Øyvind Balle said:

Thx alot :-)

This really helped me out.

I tested the aspnet_regbrowsers.exe thingy on my own server and it worked as a charm :-)

In my client's production environment on the orher hand, it was more convenient to just modify the onload event on the master page.

Again, thank you so muc :-D

# February 8, 2009 2:05 PM

milia1000 said:

Web.config pageBaseType only applies to pages that have no codebehind. I tested that with asp.net 2 + vs2008 + codebehind and it doesn't work (yes, it would be nice...).

But ClientTarget="uplevel" solves my problem with menu and safari/google chrome... so thanks!!!

My code that works (:-):

protected override void OnPreInit(EventArgs e)

{

 if (Request.UserAgent != null &&

     (Request.UserAgent.IndexOf("AppleWebKit") > 0))

 {

   this.ClientTarget = "uplevel";

 }

 base.OnPreInit(e);

 }

}

More things... Request.Browser.Adapters.Clear() works too, but if you put it on page_load, you must F5 every first time you require the page.

Thanks again!

# July 9, 2009 12:38 PM

Mark Sandfox said:

Call me dumb but none of these solutions work.  I have a very simple menu that uses Dynamic dropdown menus.  If i add a link to the top level Safari will display the top Menu, but will not display dropdown menu on hover.  I ahve tried the suggestions here and several others and they simply do not work.  I am using MS Visual Studios 2008 (asp.net 3.5) and coding in VB.Net.  Yes i converted your VC to VB.  Any help on getting the dropdwon menus to display would be greatly appreciated.  The dropdowns work in all other browsers that i know of.

# September 2, 2009 7:13 PM

Manuel Palma said:

The code has an error (not visible on page due to truncation, but visible if you copy it). Where it reads

StringComparer.CurrentCultureIgnoreCase  

it should read:

StringCompasion.CurrentCultureIgnoreCase

PS. Thanks!

# October 13, 2009 6:40 PM

Tony said:

If you use MasterPages be sure to put it in the PreRender event, otherwise the client has refresh the page after it has loaded, here's the code (in VB.NET):

Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender

       If (Request.UserAgent IsNot Nothing) AndAlso (Request.UserAgent.IndexOf("AppleWebKit") > 0) Then

           Request.Browser.Adapters.Clear()

       End If

   End Sub

BR,

Tony

# November 26, 2009 9:48 AM

Saveena said:

Bur its working very well with exploror and firefox

# December 2, 2009 4:29 AM

Dean Zimmermann said:

Wow, that fixed Safari, Chrome, & Opera all at once. With this, I can use ASP.NET menus in every major browser.  Nicely done!

# January 7, 2010 5:00 PM

Geo said:

Nice!! what about the functionality with the update panel?

# January 26, 2010 12:50 PM

Peter Wallenius said:

I tried to put your code into page_load on my masterpage, and it's working perfekt!!!

if (Request.UserAgent.IndexOf("AppleWebKit") > 0)

{

  Request.Browser.Adapters.Clear();

}

Thx.

# January 28, 2010 5:51 AM

Niraj singh said:

It tried it cut it was not helping me.

My menu control goes behind the banners used and checking the compatibility when go to menu control,to click any link then menu goes of.

# March 16, 2010 9:02 AM

wazz said:

i tried all versions here and nothing worked until i changed 0 to -1.

if (Request.UserAgent.IndexOf("AppleWebKit") > -1)

{ Request.Browser.Adapters.Clear(); }

# June 30, 2010 11:16 AM

wazz said:

actually, the code above eventually failed for me. i suppose it could be due to newer versions of .net and/or browser, or something else entirely. (only tried in safari 5.0 so far).

i found another bit of code that hasn't failed yet, here:

geekswithblogs.net/.../aspmenu-rendering-problems-in-ie8-safari-and-chrome.aspx

# July 1, 2010 9:27 AM

al said:

This post here solved my issue with asp menu control

www.s-t-f-u.com/.../asp-net-menu-control-positioning-in-safari-google-chrome

# May 6, 2011 9:53 AM

Brad M said:

Fixed me up in a hurry.  Thanks!

# June 8, 2011 1:01 PM

Marcus Rainey said:

I'm a little late to the party but I wanted to say thanks!  Walter's tips for putting the code in the master page load event was just what I needed.  Thanks again guys!

# August 5, 2011 11:44 AM

Nazish said:

Thanks a lot this solved my prob and save my life ;)

# August 23, 2011 4:16 AM

Rob Karatzas said:

this fragment doesn't make sense:

Request.UserAgent.IndexOf("AppleWebKit", StringComparer.CurrentCultureIgnoreCase)

the second parameter is an offset and has nothing to do with a stringcomparer.

# September 21, 2011 8:07 AM

khan said:

Thanx "Walter Gameiro"

i m using Menu On asp.net and run it on Chrome it greate

working Thanx Man

# October 23, 2011 7:32 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)