Я могу подтвердить, что это все еще происходит с SSRS 2005. Firefox - не единственный браузер, который не будет отображать это так, как задумал разработчик отчетов. По-видимому, IE7 (и, вероятно, IE6) предполагают, что последний атрибут стиля «победит», если для элемента назначено несколько атрибутов стиля. IE8 в стандартном режиме и Firefox предполагают первый атрибут стиля, который «победит» в этой ситуации. Я бы предположил, что все совместимые со стандартами браузеры сделают тот же выбор, что и IE8 и Firefox, хотя наша команда не проверяла это.
Я не нашел решения с точки зрения исправления, но у меня есть способ предотвратить попадание плохого HTML в браузер. OMG Ponies - спасибо за размещение этой ссылки на пост JudyX. Вуде ответил хорошим решением на 3/4 пути вниз по этому посту - к сожалению, не совсем понятно, как использовать опубликованный код.
Подход заключается в использовании фильтра ответов на странице, которая содержит элемент управления ReportViewer . Фильтр имеет доступ к необработанному HTML, который будет отправлен в браузер, что дает возможность напрямую изменять HTML, не прибегая к новой хитрости первого столбца. В нашем методе Page_Load мы устанавливаем свойство Response.Filter со следующим кодом:
protected void Page_Load(object sender, EventArgs e)
{
Response.Filter = new CorrectSSRSIssuesResponseFilter(Response.Filter);
if (!IsPostBack) {
RenderReport();
}
}
Класс CorrectSSRSIssuesResponseFilter определяется следующим образом и в основном основан на коде Водэ из поста. Секретный соус находится в методе Write (), который использует RegEx для уничтожения первого атрибута стиля:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Reports
{
public class CorrectSSRSIssuesResponseFilter : Stream
{
private Stream _sink;
private StringBuilder Output = new StringBuilder();
public CorrectSSRSIssuesResponseFilter(Stream sink)
: base()
{
_sink = sink;
}
public CorrectSSRSIssuesResponseFilter()
: base()
{
_sink = new MemoryStream();
}
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return true; } }
public override bool CanWrite { get { return true; } }
public override void Flush()
{
_sink.Flush();
}
public override long Length
{
get { return _sink.Length; }
}
public override long Position
{
get
{ return _sink.Position; }
set
{ _sink.Position = value; }
}
public override int Read(byte[] buffer, int offset, int count)
{
return _sink.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return _sink.Seek(offset, origin);
}
public override void SetLength(long value)
{
_sink.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
string strBuffer = UTF8Encoding.UTF8.GetString(buffer, offset, count);
//A Closing HTML tag indicates the response object has finished recieving the entire content of the page
strBuffer = System.Text.RegularExpressions.Regex.Replace(
strBuffer
, "<TD style=\"[^\"]*\" style=(?<goodStyle>\"[^\"]*\")>"
, "<TD style=${goodStyle}>"
, System.Text.RegularExpressions.RegexOptions.Compiled
);
buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
_sink.Write(buffer, offset, buffer.Length);
}
}
}