gpt4 book ai didi

reporting-services - SSRS 报告查看器控件浏览器兼容性

转载 作者:行者123 更新时间:2023-12-04 00:08:25 29 4
gpt4 key购买 nike

MS Report Viewer Control 与 Firefox 和 Safari 等浏览器的兼容性如何?

如果您知道 SSRS 的任何 3rd 方报告查看器,也请发帖。

最佳答案

编辑 - 2016/2017 更新

SSRS 2016+ 可以说是跨浏览器兼容的。
表格边框在 IE10 中没有正确显示,但无论如何 IE10 正在消亡。
在其他浏览器中,这很好。

还是需要注册add_pageLoaded来翻译参数提示。

Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function () { fixReportingServices('rpt-container'); });

此外,就像在 <2016 版本中一样,您需要将 PageCountMode="Actual" 添加到 RS:ReportViewerHost 控件中。
<RS:ReportViewerHost ID="ReportViewerControl" PageCountMode="Actual" runat="server" />

如果你想有有意义的分页号码。

此外,当您使用日期选择器(SSRS < 2016 以及)在查询字符串中设置语言时会出现问题。如果您希望 datepicker 使用非浏览器语言,则需要将 context.Request.UserLanguages[i] 设置为 HTTP 模块中 context.BeginRequest 中的查询字符串中指定的语言。

此外,如果您想在 Internet 的 iframe 中安全地使用 SSRS,您需要在每个 HTTP 响应中添加 X-Frame-Options 和 Content-Security-Policy HTTP header 。见 my github-repository for details
</EndEdit>

2016 年之前:

我可以告诉你,我有 9 年的经验(SSRS 2005、SSRS 2008 R1 & R2、2012 和 SSRS 2014)。

让我向您保证,因为 SSRS HTML 报告依赖于 IE5-Quirksmode,所以它们不可能在除 Internet Explorer 之外的任何浏览器中正确呈现(我可能倾向于添加 IE < 10)。

如果您拥有报表服务器的管理员访问权限,并且我强调 IF,您可以在 ReportViewer 页面上添加 jQuery 例程和 CSS 以纠正最基本的问题(例如您看不到超过 1 厘米的报表),但除此之外,HTML 呈现仍然看起来非常糟糕(边距、表格边框、图片填充、列大小、文本字段大小、标题和/或页码对齐等,简而言之 - 几乎任何东西)

当然,ActiveX 打印机控件只能在 InternetExplorer(在 Windows 上)中工作,因为只有那里支持 ActiveX。

让我也向你保证,绝对没有办法让 ReportManager 在 IE 之外的任何其他浏览器中工作。

至于 Internet Explorer 支持,应该提到的是,从 IE 版本 10 开始,IE 默认使用 webkit-quirksmode(出于兼容性原因)而不是 IE5 quirksmode,因此呈现的 HTML 看起来与 Chrome/Firefox/Safari 中一样可怕对于 IE 10+,除非您在 ReportViewer.aspx 页面中添加了与 meta xua 兼容的 IE5。

后者可能不适用于 Intranet,因为 IE 在 Intranet 站点上时会自动回退到 IE 7 兼容模式(但仅限于任何 Windows 版本 < 8 )。

在 Windows 8 中,localhost 链接和计算机名链接(无法在 stackoverflow 帖子中添加 http://)未分配到本地 Intranet 区域(可能是因为快速破解,因此 IE 不会退回到 IE7 兼容模式),并且因此,Windows 身份验证将失败。

还应该提到的是,不可能为 ReportManager 添加与 meta xua 兼容的 IE5,因为没有您可以编辑的页面(编译的不可更新的 ASP.NET 网站项目...)。

由于没有使用开发工具在 quirksmode 中切换 reportmanager,因此无法在 IE 10+ 中使用 ReportManager。

然后,要提到的另一件事是,从 IE9 开始,IE 从父页面继承 iframe 元素的 doctype,并且根本无法更改它(无需将父页面更改为所需的子页面文档-模式)。

因此,如果您足够聪明,可以将 iframe 用于报告,因为在弹出窗口阻止程序的时代,任何理智的人都不可能想要弹出窗口,报告页面将继承父页面的文档类型。如果这不是 IE5-QuirksMode,它将呈现与 Safari/Chrome/Firefox/Opera 对于任何 IE > 8 的报告同样可怕,而不管 ReportViewer.aspx 中任何可能的与元 xua 兼容的 ie5 标记。

至于替代品,免费且具有类似功能集,只有 Eclipse BIRT(幸运的是,HTML 渲染不相似)。

应该提到的是,虽然 BIRT 根据 Eclipse 公共(public)许可证获得许可,但使用 SUN Java,因此您使用的是 Oracle 技术,该技术受其各自许可条款的约束。
此外,您使用的是非 Microsoft 技术,并且 Excel-Sheets BIRT 渲染实际上是 XML 文件,在 Office 2010+ 中打开时会产生(谁会猜到)相当惊人的警告。

然后,收取相当大的费用,有 http://www.stimulsoft.com 报告和 Telerik 报告。
从技术角度来看,我建议使用 stimulsoft 报告,但是:免责声明,我没有使用过其中任何一个,因为它们不是免费的。

至于替代的 SSRS 渲染引擎(顺便说一句,不是查看器),只有 www.fyireporting.com/,这里有一个分支 http://www.codeproject.com/Articles/138271/An-Open-Source-RDL-Engine

但是 fyiReporting 不完整并且正在进行中(如果没有被放弃),所以我不会使用它。

最重要的是,如果您的产品仅是 IE 和 windows,并且 windows 版本 < 8(并且不 - 不是 <= 以防万一您没有注意),在 Intranet 中,从弹出窗口而不是 iframe 调用,然后去与 SSRS。
对于其他任何事情,请使用 stimulsoft 报告(问题是,您必须重做所有报告,因为没有自动迁移 - 甚至没有非工作报告)。

PS:
通过添加“一点 javascript”,我的意思是下面的内容(2008 R1 版,不适用于 2008R2+,可能适用于 2005,并注意您需要将 jQuery 和 jQuery Migrate 嵌入内联脚本标记中,如果客户端 PC 无权访问 http(s)://ajax.aspnetcdn.com [注意:将脚本放入 Pages 文件夹并添加相对或绝对链接将不起作用...]):
<%@ Register TagPrefix="RS" Namespace="Microsoft.ReportingServices.WebServer" Assembly="ReportingServicesWebServer" %>
<%@ Page Language="C#" AutoEventWireup="true" Inherits="Microsoft.ReportingServices.WebServer.ReportViewerPage" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<%= System.Web.HttpContext.Current.Request.Browser.Browser == "IE" && System.Globalization.CultureInfo.InvariantCulture.CompareInfo.IndexOf(System.Convert.ToString(System.Web.HttpContext.Current.Request.QueryString), "stylesheet", System.Globalization.CompareOptions.IgnoreCase) == -1 ? (System.Web.HttpContext.Current.Request.Browser.Browser != "IE" ? "": "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=5\">") : "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">" %>

<head id="headID" runat="server">
<title>Report Viewer</title>




<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/jquery.migrate/jquery-migrate-1.1.0.min.js"></script>



<script type="text/javascript">

var bInFrameOrIframe = false;
var iLanguageIndex = 0;
var language = "DE_LOL";
var UpdateLock = false;



if (window.self === window.top) {
// alert("true");
// not in a frame
// Use IE5 quirksmode
//document.writeln('<meta http-equiv="X-UA-Compatible" content="IE=5" />');
bInFrameOrIframe = false
}
else {
// in a frame, FMS
bInFrameOrIframe = true;
}


function TranslateParameterPrompts() {

//mTo = false;
$("table[id^='ParametersGridReportViewerControl'] span").each(function(index) {
var strText = $(this).text();
if (strText != null && strText.indexOf('/') != -1) {
strText = strText.split('/');
if (iLanguageIndex < strText.length)
strText = strText[iLanguageIndex];
else {
if (strText.length > 0)
strText = strText[0];
}

$(this).text(strText);
}

});

//setTimeout(function(){mTo = true}, 5000);
}


function setTableSize() {
//$("[id$='ReportViewerControl']")
$(
$(
$("#ReportFrameReportViewerControl")[0].contentWindow.document
)
.find("[id$='report']")[0].contentWindow.document.body
).find('*')
.each(function() {
//console.log("Processing an element");
//var cls = $(this).attr("class");

try {

// Don't add a border to sort-arrow
if ($(this).is('img')) {
return;
}


var anywidth = $(this).css('width');
var anywidth = parseFloat(anywidth);
//console.log("anywidth: " + anywidth);


//var lol = $(this).css('borderLeftWidth');
var blw = $(this).css('border-left-width');
var brw = $(this).css('border-right-width');
var btw = $(this).css('border-top-width');
var bbw = $(this).css('border-bottom-width');

var borls = $(this).css('border-left-style') == "solid";
var borrs = $(this).css('border-right-style') == "solid";
var borts = $(this).css('border-top-style') == "solid";
var borbs = $(this).css('border-bottom-style') == "solid";



var blw = parseFloat(blw);
var brw = parseFloat(brw);
var btw = parseFloat(btw);
var bbw = parseFloat(bbw);

//parseInt($(this).css("borderRightWidth"))
//console.log(parseInt($(this).css("borderLeftWidth")));

UpdateLock = true;


// Set width to 1px where 0px
if (anywidth == 0)
$(this).css('width', '1px');


if (borls && blw == 0.0 || (blw > 0.0 && blw < 1.0)) {
//console.log("setting border width");
$(this).css('border-left-width', '1px');
}

if (borrs && brw == 0.0 || (brw > 0.0 && brw < 1.0)) {
$(this).css('border-right-width', '1px');
}

if (borts && btw == 0.0 || (btw > 0.0 && btw < 1.0)) {
$(this).css('border-top-width', '1px');
}

if (borbs && bbw == 0.0 || (bbw > 0.0 && bbw < 1.0)) {
$(this).css('border-bottom-width', '1px');
}

UpdateLock = false;
}
catch (ex) {
UpdateLock = false;
//console.log(ex);
}

}); // End $('*').each

// console.log("loop");




var $img = $("img[onload^='this.fitproportional=true']");
if ($img == null) {
// console.log("img is null");
return;
}
var $div = $img.parent();
if ($div == null) {
// console.log("div is null");
return;
}

UpdateLock = true;
{
$img.removeAttr("height");
$img.css('max-width', '100%')
$img.css('max-height', '100%')

$div.css('text-align', 'right');

var divMinWidth = parseFloat($div.css('min-width'));
var divWidth = parseFloat($div.css('width'));

var divMinHeight = parseFloat($div.css('min-height'));
var divHeight = parseFloat($div.css('height'));

// console.log("width: " + divWidth);
// console.log("height: " + divHeight);
// console.log("min-width: " + divMinWidth);
// console.log("min-height: " + divMinHeight);

if (divMinWidth != 0)
$div.css('width', $div.css('min-width'));

if (divMinHeight != 0)
$div.css('height', $div.css('min-height'));

}
UpdateLock = false;

}


$(document).ready(function() {

switch (language) {
case "fr":
iLanguageIndex = 1;
break;
case "it":
iLanguageIndex = 2;
break;
case "en":
iLanguageIndex = 3;
break;
default: // "DE"
iLanguageIndex = 0;
}

TranslateParameterPrompts();
// setInterval(function() { TranslateParameterPrompts() }, 100);


if ($.browser.msie && !bInFrameOrIframe)
return;

// if ($.browser.webkit)
//setTableSize();

$("[id$='ReportFrameReportViewerControl']").load(function() {
//setNewHeight();
//alert("Loading");

setTableSize();

$(
$("[id$='ReportFrameReportViewerControl']")[0].contentWindow.document
)
.find("[id$='report']").load(function() {
//alert("load report");
setTableSize();
}
); // End load #report

}); // End Function load #ReportFrameReportViewerControl

}); // End Function document.ready

</script>

</head>
<body style="margin: 0px; overflow: auto">
<form style="width:100%;height:100%" runat="server" ID="ReportViewerForm">
<RS:ReportViewerHost ID="ReportViewerControl" runat="server" />
</form>
</body>
</html>

注意:UpdateLock 源于 2012 backport,这里并没有真正使用,而且语言也源于 backport,2012 年需要在 TranslateParameterPrompts 上设置间隔
和功能
2012 年在 jQuery 选择器中只添加了一点“标签”......
    function TranslateParameterPrompts() {

//mTo = false;
$("table[id^='ParametersGridReportViewerControl'] label span").each(function(index) {
var strText = $(this).text();
if (strText != null && strText.indexOf('/') != -1) {
strText = strText.split('/');
if (iLanguageIndex < strText.length)
strText = strText[iLanguageIndex];
else
{
if(strText.length > 0)
strText = strText[0];
}

$(this).text(strText);
}

});

//setTimeout(function(){mTo = true}, 5000);
}

从浏览器语言推断语言是这样的,顺便说一句:
<script type="text/javascript">
language = <%= System.Web.HttpContext.Current.Request.UserLanguages != null ? "\"" + System.Convert.ToString(System.Web.HttpContext.Current.Request.UserLanguages[0]) + "\"" : "null" %>;

if(language == null)
language = window.navigator.userLanguage || window.navigator.language;

if(language != null)
language = language.substr(0,2).toLowerCase();

</script>

并且在 2012 年您需要处理 session cookie,否则在打开大约 120 个报告后您会收到“HTTP 400: Header too long”:
<script type="text/C#" runat="server">
protected string ClearSessionKeepAliveCookiesToPreventHttp400HeaderTooLong()
{
if(Request == null || Request.Cookies == null)
return "";

if(Request.Cookies.Count < 60)
return "";

// System.Web.HttpContext.Current.Response.Write("<h1>"+Request.Cookies.Count.ToString()+"</h1>");
for(int i = 0; i < System.Web.HttpContext.Current.Request.Cookies.Count; ++i)
{
if(StringComparer.OrdinalIgnoreCase.Equals(Request.Cookies[i].Name, System.Web.Security.FormsAuthentication.FormsCookieName))
continue;

if(!Request.Cookies[i].Name.EndsWith("_SKA", System.StringComparison.OrdinalIgnoreCase))
continue;

if(i > 60)
break;

//System.Web.HttpContext.Current.Response.Write("<h1>"+Request.Cookies[i].Name+"</h1>");

System.Web.HttpCookie c = new System.Web.HttpCookie( Request.Cookies[i].Name );
//c.Expires = System.DateTime.Now.AddDays( -1 );
c.Expires = new System.DateTime(1970, 1 ,1);
c.Path = Request.ApplicationPath + "/Pages";
c.Secure = false;
c.HttpOnly = true;

// http://stackoverflow.com/questions/5517273/httpcookiecollection-add-vs-httpcookiecollection-set-does-the-request-cookies
//Response.Cookies[Request.Cookies[i].Name] = c;
//Response.Cookies.Add(c);
Response.Cookies.Set(c);
}

return "";
}


</script>

而在2012年,你需要听内容更新,因为它使用了微软的Ajax控件
function cbOnContentUpdate() {
//console.log("content update");
alterTableBorderWidth();
// TranslateParameterPrompts();
} // End Callback cbOnContentUpdate


var hLastTimeout = null;

function queueUpdate() {

if (UpdateLock)
return;


if (hLastTimeout != null)
clearTimeout(hLastTimeout);

hLastTimeout = window.setTimeout(function() { cbOnContentUpdate(); }, 50);

//window.setTimeout(function() { cbOnContentUpdate(); }, 3000);
} // End Function queueUpdate


$(document).ready(function() {

switch (language) {
case "fr":
iLanguageIndex = 1;
break;
case "it":
iLanguageIndex = 2;
break;
case "en":
iLanguageIndex = 3;
break;
default: // "DE"
iLanguageIndex = 0;
}

setInterval(function() { TranslateParameterPrompts() }, 100);

// opt-out for non-framed IE, because that crook supports IE5-Quirks (framed takes parent-doctype in IE >= 9)
if ($.browser.msie && !areWeInFrame())
return;


// if ($.browser.webkit)

// console.log('Setting event listener!');

// http://stackoverflow.com/questions/4979738/fire-jquery-event-on-div-change
//$("[id$='ReportViewerControl']").bind('DOMNodeInserted DOMNodeRemoved', function(event) {
//$("[id$='ReportArea']")
$("body")
.bind('DOMNodeInserted DOMNodeRemoved DOMSubtreeModified', function(event) {

if (event.type == 'DOMNodeInserted') {
//console.log('Content added! Current content:' + '\n\n' + this.innerHTML);
//console.log('Content added!');
queueUpdate();
}
else {
//console.log('Content removed! Current content:' + '\n\n' + this.innerHTML);
//console.log('Content removed!');
queueUpdate();
}
}); // End Bind IRM

}); // End Function $(document).ready

请注意,对于 2012 年,setTableSize 是 alterTableBorderWidth,并且选择器如下所示:
 function alterTableBorderWidth() 
{
//$('*')
$("[id$='ReportViewerControl']").find('*')
.each(function() {

顺便说一句,如果你想删除打印图标,因为它只是一个悲伤的来源,就像这样(德语,英语,法语和意大利语[瑞士语言+英语])。

此 CSS 适用于 2008 R1,不知道也不关心它是否与 2012 年相同。
input[type="image"][title="Drucken"], input[type="image"][title="Print"], input[type="image"][title="Imprimer"], input[type="image"][title="Stampa"]
{
display: none !important;
}

如果这仍然不能阻止您,那么请继续并在 SSRS 2012 中使用表单例份验证(提示 1:对于 2005-2008R2,没有 ms 提供的示例,您需要自己编写);)

提示 2:如果您遵循提示 1,当 URL 中有冒号 [bug?] 时,表单例份验证重定向将不起作用,您可以从 mono 窃取代码并编写自己的重定向。

提示 3:如果您遵循了提示 2 并让表单例份验证正常工作,那么您可能想要更改您要编写的上传工具,因为您不喜欢手动“为每个报告浏览目录 - 选中允许覆盖复选框 -上传报告 - 设置数据源)为 120 个左右的报告,那么您将从 ReportingService2005 继承一个类并覆盖 GetWebRequest 和 GetWebResponse
''' <summary>
''' Overriding the method defined in the base class.
''' </summary>
''' <param name="uri"></param>
''' <returns></returns>
Protected Overrides Function GetWebRequest(uri As Uri) As System.Net.WebRequest
Dim request As System.Net.HttpWebRequest
request = DirectCast(System.Net.HttpWebRequest.Create(uri), System.Net.HttpWebRequest)
request.Credentials = MyBase.Credentials
request.CookieContainer = New System.Net.CookieContainer()

If m_authCookie IsNot Nothing Then
request.CookieContainer.Add(m_authCookie)
End If

Return request
End Function ' GetWebRequest



''' <summary>
''' Overriding the method defined in the base class.
''' </summary>
''' <param name="request"></param>
''' <returns></returns>
Protected Overrides Function GetWebResponse(request As System.Net.WebRequest) As System.Net.WebResponse
Dim response As System.Net.WebResponse = MyBase.GetWebResponse(request)

' http://social.msdn.microsoft.com/Forums/sqlserver/en-US/f68c3f2f-c498-4566-8ba4-ffd5070b8f7f/problem-with-ssrs-forms-authentication
Dim cookieName As String = response.Headers("RSAuthenticationHeader")
If cookieName IsNot Nothing Then
m_authCookieName = cookieName
Dim webResponse As System.Net.HttpWebResponse = DirectCast(response, System.Net.HttpWebResponse)
Dim authCookie As System.Net.Cookie = webResponse.Cookies(cookieName)

' Save it for future reference and use.
m_authCookie = authCookie
End If

Return response
End Function ' GetWebResponse

提示 4:如果您没有在 SSRS 2008 R2 上安装 Service Pack 1 + 2,上述方法将不起作用...

提示 5:TranslateParameters 方法存在是因为您无法(按设计)通过 SSRS 将参数提示翻译成多种语言,因此您编写:
Raum / Local / Locale / Room 

它使用架构:
Text_DE / Text_FR / Text_IT / Text_EN

然后在文本上按 '/' 进行拆分(如果您的提示文本在某处包含 '/',这很容易出错),然后通过选择 MIN(splitarray.length, index) 按语言索引选择正确的文本) 顺便说一句,以防万一你只有 Text_DE/Text_FR 或其他什么,当然首先检查文本是否包含“/”。

提示 6:
我需要继续吗? (我仍然可以将这篇文章扩大到十倍,但我想我现在应该回去工作了:))

如果您想看看它的外观如何,这就是 vanilla ssrs 在 chrome 中的呈现方式

Vanilla SSRS chrome

这就是 IE11 中的样子,通过 xua 设置了 IE5 兼容性

Geb

这就是它应该是什么,以及你可以通过大量修改 javascript 和 CSS 来渲染它
SSRS in Chrome with CSS and JS applied

附录:
哦,它变得更好了

如果要以应用程序指定的语言(与浏览器语言不同)运行 reportviewer,则需要将 reportviewer 的文化设置为查询字符串中指定的文化...
<script type="text/C#" runat="server">
protected override void InitializeCulture()
{
string sprache = System.Web.HttpContext.Current.Request.QueryString["in_sprache"];

// System.Web.HttpContext.Current.Response.Write(sprache);

switch(System.Globalization.CultureInfo.InvariantCulture.TextInfo.ToLower(sprache))
{
case "fr":
sprache = "fr-CH";
break;
case "it":
sprache = "it-CH";
break;
case "en":
sprache = "en-US";
break;
default:
sprache = "de-CH";
break;
}

// System.Web.HttpContext.Current.Response.Write(sprache);

System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(sprache);
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(sprache);
base.InitializeCulture();
}



</script>

如果要设置静态文化,可以在页面声明中进行
<%@ Page UICulture="de" Culture="de-CH" %>

如果您尝试删除打印图标和 atom-feed,使用样式进行操作,无论如何,它只能在 Chrome 中工作......
    input[type="image"][title="Drucken"], input[type="image"][title="Print"],    input[type="image"][title="Imprimer"], input[type="image"][title="Stampa"]
{
display: none !important;
}


input[type="image"][title="In Datenfeed exportieren"], input[type="image"][title="Exporter vers un flux de données"], input[type="image"][title="Esporta in feed di dati"], input[type="image"][title="Export to Data Feed"]
{
display: none !important;
}
*/
input[type="image"][src$="Microsoft.Reporting.WebForms.Icons.Print.gif"] {
display: none !important;
}

input[type="image"][src$="Microsoft.Reporting.WebForms.Icons.AtomDataFeed.gif"] {
display: none !important;
}

但是您实际上可以通过将 ShowPrintButton="false" 添加到 reportviewer 控件来至少删除 internet-explorer 中的打印图标:
<RS:ReportViewerHost ID="ReportViewerControl" ShowPrintButton="false" runat="server" />

另一个想法:在 SSRS 2012 和 2014(可能还有 2008R2)中,您还可以将修复 SSRS 的 javaScript 方法添加到 ScriptManager 的 add_pageLoaded 中。像这样:
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function () { fixReportingServices('rpt-container'); });

这样您就不必监听页面更改事件,这会加快速度,因为加载仅在每次更新结束时调用一次。

警告

因为在Internet上,IE并没有默认兼容 View ,
<meta http-equiv="X-UA-Compatible" content="IE=5">

也不会帮助您解决某些问题(rotate270 文本/垂直文本)。

即使在 IE 中,它也只有在内网中才能正常工作,因为只有这样它才会使用“兼容性 View ”。虽然元标记将浏览器设置为 IE5-Quirksmode,但它并没有启用“兼容性 View ”,因此它不是真正的 quirksmode...

关于reporting-services - SSRS 报告查看器控件浏览器兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/596479/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com