[转载]如何使.net开发的程序正确支持firefox等非ie浏览器
Wednesday, 26. October 2005, 02:36:18
http://dev.codelphi.com/virushuo/archive/2004/08/27/20311.aspx
本文的完成,需要感谢adex的帮助。
用firefox去看asp.net做的网站,一般是很不爽的。所有的内容都像被风吹晕了一样往左边斜。就像这样:

IE里面则是这样的:
以前我并没有在意过这个问题,总觉得是作页面的时候做得不好。(关于页面的知识我很bc,就算在意估计也不会有什么结果)。今天,同事Adex发现了这个 现象的原因--asp.net的服务器控件在不同的浏览器中render出来的结果是不一样的。在firefox和ie中分别是这样的:
- firefox:
-
<table id="panLogin" cellpadding="0" cellspacing="0" border="0" width="100%"> - ie:
<div id="panLogin">
这下清楚了,本来好好的div,在firefox中变成了table。怪不得无论如何都往左偏。
- 用Reflector反编译system.web.dll的代码,在HtmlTextWriter类中可看到如下代码:
protected virtual HtmlTextWriterTag GetTagKey(string tagName)
{
if ((tagName != null) && (tagName.Length > 0))
{
object obj1 = HtmlTextWriter._tagKeyLookupTable[tagName.ToLower(CultureInfo.InvariantCulture)];
if (obj1 != null)
{
return ((HtmlTextWriterTag) obj1);
}
}
return HtmlTextWriterTag.Unknown;
}- 这段代码在其子类Html32TextWriter中被重载为
protected override string GetTagName(HtmlTextWriterTag tagKey)
{
if (tagKey == HtmlTextWriterTag.Div)
{
return "table";
}
return base.GetTagName(tagKey);
}
明显,div被替换成了table。
- 为什么如此呢?请看这两篇文章
- http://aspnet.4guysfromrolla.com/articles/050504-1.aspx
- http://slingfive.com/pages/code/browserCaps/
比较长,我就不翻译了。
- 简单的说,就是在machine.config里面的<browserCaps>节点,定义了一些判断useragent的表达式。其中对ie的判断是这样的:
<case match="^Mozilla[^(]*\(compatible; MSIE <snip>">
browser=IE
...
tagwriter=System.Web.UI.HtmlTextWriter
</case>- 而对mozilla5/firefox呢?是这样的:
<case match="^Mozilla/5\.0 \([^)]*\) (Gecko/[-\d]+ )?Netscape6/(?'version'(?'major'\d+)(?'minor'\.\d+)(?'letters'\w*)).*">
首先,这段正则表达式错了,firefox和mozilla5的useragent都没有包含Netscape6。然后,这段代码也没有让他们使用 HtmlTextWriter。也就是说,mozilla5/firefox只能得到html3.2的代码。
- 解决的方法很简单,用这个老外写的代码就可以,不仅解决了firefox的问题,好像还能解决mac机上的问题,不过我没测试mac。代码如下:
<!-- 2003-12-03, Rob Eberhardt - http://slingfive.com/demos/browserCaps/ -->
<browserCaps>
<!-- GECKO Based Browsers (Netscape 6+, Mozilla/Firebird, ...) //-->
<case match="^Mozilla/5\.0 \([^)]*\) (Gecko/[-\d]+)? (?'type'[^/\d]*)([\d]*)/(?'version'(?'major'\d+)(?'minor'\.\d+)(?'letters'\w*)).*">
browser=Gecko
type=${type}
frames=true
tables=true
cookies=true
javascript=true
javaapplets=true
ecmascriptversion=1.5
w3cdomversion=1.0
css1=true
css2=true
xml=true
tagwriter=System.Web.UI.HtmlTextWriter
<case match="rv:(?'version'(?'major'\d+)(?'minor'\.\d+)(?'letters'\w*))">
version=${version}
majorversion=${major}
minorversion=${minor}
<case match="^b" with="${letters}">
beta=true
</case>
</case>
</case>
<!-- AppleWebKit Based Browsers (Safari...) //-->
<case match="AppleWebKit/(?'version'(?'major'\d)(?'minor'\d+)(?'letters'\w*))">
browser=AppleWebKit
version=${version}
majorversion=${major}
minorversion=0.${minor}
frames=true
tables=true
cookies=true
javascript=true
javaapplets=true
ecmascriptversion=1.5
w3cdomversion=1.0
css1=true
css2=true
xml=true
tagwriter=System.Web.UI.HtmlTextWriter
<case match="AppleWebKit/(?'version'(?'major'\d)(?'minor'\d+)(?'letters'\w*))( \(KHTML, like Gecko\) )?(?'type'[^/\d]*)/.*$">
type=${type}
</case>
</case>
<!-- Konqueror //-->
<case match = "Konqueror/(?'version'(?'major'\d+)(?'minor'\.\d+)(?'letters'));\w*(?'platform'[^\)]*)">
browser=Konqueror
version=${version}
majorversion=${major}
minorversion=${minor}
platform=${platform}
type=Konqueror
frames=true
tables=true
cookies=true
javascript=true
javaapplets=true
ecmascriptversion=1.5
w3cdomversion=1.0
css1=true
css2=true
xml=true
tagwriter=System.Web.UI.HtmlTextWriter
</case>
</browserCaps>
为了避免在每台机器上配置的麻烦,可以在项目的web.config中加入这段代码。试试看,是不是table变成div了?
题外话:这个错误有点弱智,我不太相信ms能犯这样的错误,其实我更倾向于相信这是故意的。要么就是他们真的认为除了IE,别的浏览器都不能正确的支持html4.0。殊不知,支持最差得反而是IE。
英文网站提到这个问题的很多,但中文的竟然一个没有。这是一件可怕的事情,可见中国的.net程序员眼中只有IE,没有其他浏览器。这是何等悲哀的事情。














