当前位置:  开发笔记 > 编程语言 > 正文

SSRS Report Viewer控制浏览器兼容性

如何解决《SSRSReportViewer控制浏览器兼容性》经验,为你挑选了1个好方法。

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

如果您知道SSRS的任何第三方报告查看者,也请发布.



1> Stefan Steig..:

编辑 - 2016/2017更新

SSRS 2016+可以说是跨浏览器兼容的.
表格边框在IE10中没有正确显示,但无论如何IE10正在消失.
在其他浏览器中,它没问题.

您仍需要注册add_pageLoaded才能翻译参数提示.

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

此外,像在版本<2016年,你需要添加PageCountMode="Actual"RS:ReportViewerHost控制.


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

此外,当您使用datepickers在查询字符串中设置语言时也存在问题(SSRS <2016也是如此).context.Request.UserLanguages[i]如果希望datepicker使用非浏览器语言,则需要在HTTP模块中的context.BeginRequest中设置查询字符串中指定的语言.

此外,如果要安全地在Internet中的iframe中使用SSRS,则需要在每个HTTP响应中添加X-Frame-Options和Content-Security-Policy HTTP-headers.有关详细信息,请参阅我的github-repository.


预-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网站项目......).
如果没有使用dev-tools在quirksmode中切换reportmanager,那么在IE 10+中就不可能使用ReportManager.

然后,另外要提到的是,从IE9开始,IE从父页面继承了iframe元素的doctype,并且也没有办法改变它(不将父页面更改为所需的子页面doc -模式).

因此,如果你足够聪明地使用iframe作为报告,因为在弹出窗口阻止程序时代任何理智的人都不想要弹出窗口,报告页面将继承父页面的doctype.如果这不是IE5-QuirksMode,它将使报告与Safari/Chrome/Firefox/Opera上的任何IE> 8一样可怕,而不管ReportViewer.aspx中任何可能的与meta xua兼容的ie5标记.

至于替代方案,免费且具有类似的功能集,只有Eclipse BIRT(幸运的是,HTML呈现并不相似).

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

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

至于替代的SSRS渲染引擎(不是观众btw),只有www.fyireporting.com/ ?,这里有一个分支http://www.codeproject.com/Articles/138271/An-Open-Source-RDL-发动机.

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


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

PS:
And by adding "a little javascript", i mean the below thing(2008 R1 Edition, won't work on 2008R2+, may work on 2005, and note that you need to embed jQuery and jQuery Migrate in an inline-script tag, if the client PC's don't have access to http(s)://ajax.aspnetcdn.com [note: putting the scripts into the Pages folder and adding a relative or absolute link won't work...]):

<%@ Register TagPrefix="RS" Namespace="Microsoft.ReportingServices.WebServer" Assembly="ReportingServicesWebServer" %>
<%@ Page Language="C#" AutoEventWireup="true" Inherits="Microsoft.ReportingServices.WebServer.ReportViewerPage" %>



<%= 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" ? "": "") : "" %>

    
    Report Viewer




    
    



    



    

Note: UpdateLock stems from 2012 backport and is not really used here, and language stems from backport too, setInterval on TranslateParameterPrompts is necessary in 2012 and function for 2012 has only the little addition of "label" in the jQuery selector...

    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);
    }

Infering the language from the browser language goes like this, btw:


And in 2012 you need to Dispose of the session cookies, otherwise you get "HTTP 400: Header too long" after opening about 120 reports:


And on 2012, you need to listen to content update, because it uses Microsoft Ajax controls

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

And note that for 2012, setTableSize is alterTableBorderWidth, and the selector goes like this:

 function alterTableBorderWidth() 
        {
            //$('*')
            $("[id$='ReportViewerControl']").find('*')
            .each(function() {

Btw, if you want to remove the PRINT icon, because it's only a source of sorrow, that goes like this (for German, English, French and Italian [the languages spoken in Switzerland + English]).

This CSS is for 2008 R1, don't know and care if it's the same in 2012.

input[type="image"][title="Drucken"], input[type="image"][title="Print"], input[type="image"][title="Imprimer"], input[type="image"][title="Stampa"]
{
    display: none !important;
}

And if that still doesn't deter you, then go right ahead and use forms authentication in SSRS 2012 (hint 1: there is no ms-provied sample as for 2005-2008R2, you need to write it yourself) ;)

Hint2: if you followed hint1, forms authentication redirect doesn't work when you have a colon in the URL [bug?], you can steal the code from mono and write your own redirect.

Hint3: if you followed hint2 and got forms authentication working, then you probably want to change the upload tool you're going to write, because you won't like to do manually "for each report browse-directory - check allow override checkbox - upload report - set datasource) for 120 reports or so, then you will be inheriting a class from ReportingService2005 and override GetWebRequest and GetWebResponse

''' 
''' Overriding the method defined in the base class.
''' 
''' 
''' 
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 



''' 
''' Overriding the method defined in the base class.
''' 
''' 
''' 
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 

Hint 4: The above methods won't work if you haven't installed service pack 1 + 2 on SSRS 2008 R2...

Hint 5: The TranslateParameters method is there because you cannot (by design) translate the parameter prompts to multiple languages by SSRS, so you write:

Raum / Local / Locale / Room 

which uses schema:

Text_DE / Text_FR / Text_IT / Text_EN

And then do split by '/' on the text (which is a little error prone if your prompt text contains '/' somewhere), and then select the right text by index of the language, by choosing MIN(splitarray.length, index) btw, just in case somewhere you only have Text_DE/Text_FR or whatever, first checking if the text contains a '/' at all, of course.

Hint 6: Need I go on ? (i could still expand this post to tenfold size, but I think I should go back to work now :) )

If you want to see just how f*up it looks, this is how vanilla ssrs renders in chrome

Vanilla SSRS chrome

This is what it looks like in IE11, with IE5 compatibility set via xua

Geb

And this is what it should be, and what you can get it to render with much tinkering with javascript and CSS SSRS in Chrome with CSS and JS applied

Addendum:
Oh, and it gets even better

If you want to run reportviewer in a language specified by your application (which is NOT identical to the browser language), you need to set the culture of reportviewer to the culture specified in your query string...


If you want to set a static culture, you can do so in the page declaration

<%@ Page UICulture="de" Culture="de-CH" %>

And if you try to remove the the print icon and the atom-feed, doing it with styles, no matter how, it only works in 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;
    }

But you can actually remove at least the print icon in internet-explorer by adding ShowPrintButton="false" to the reportviewer control:


Another idea: in SSRS 2012 & 2014 (and possibly 2008R2), you can also add your SSRS-fixing javaScript method into add_pageLoaded of ScriptManager. Like this:

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

Then you don't have to listen to page change events, which speeds things up, because loaded is only called once at the end of each update.

WARNING

Because in the Internet, IE doesn't default to compatibility view,


won't help you with certain issues either (rotate270 text/vertical text).

Even in IE, it only works properly when you are in the intranet, because only then it uses "compatibility view". While the meta-tag sets the brower into IE5-Quirksmode, it doesn't enable "compatibility view", so it isn't the true quirksmode...

推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有