Disabling Export Formats in Reporting Services

Reporting Services 2005 doesn’t allow you to selectively disable export formats for your reports. You can disable export formats for the whole server, but this is a bit useless in a shared environment. For my current client, we wanted to disable XML, Tiff and “web archive” export on all of our reports, but not affect any other reporting applications deployed on the server.

Our reports consist of custom parameter pages followed by a report view page onto which we’ve dropped a ReportViewer control. When the page loads, we programatically set the ReportViewer’s server URL, report path, and parameters. We’re doing this to ensure users are requesting reports for data that they’re allowed to see and not tricking us into revealing other users’ data.

Whilst there’s no official way to disable export formats on an individual report, a little bit of exploration using Reflector reveals that the ReportViewer contains a ServerReport that acts as a proxy between the control and the Reporting Services web service. The ServerReport allows you to list rendering extensions—these guys do the hard work of actually exporting in each format—but it doesn’t allow you to set the visibility of an extension. Reflection to the rescue!

The following code sample turns off XML, Tiff, and “web archive” export for a particular ReportViewer or ServerReport:

using System.Reflection;
using Microsoft.Reporting.WebForms;
using Microsoft.SqlServer.ReportingServices2005.Execution;

namespace MyProject
{
    public class ServerReportDecorator
    {
        private readonly ServerReport serverReport;

        public ServerReportDecorator(ReportViewer reportViewer)
        {
            this.serverReport = reportViewer.ServerReport;
        }

        public ServerReportDecorator(ServerReport serverReport)
        {
            this.serverReport = serverReport;
        }

        public void DisableUnwantedExportFormats()
        {
            foreach(RenderingExtension extension in serverReport.ListRenderingExtensions())
            {
                if(extension.Name == "XML" || extension.Name == "IMAGE"
		                           || extension.Name == "MHTML")
                    ReflectivelySetVisibilityFalse(extension);
            }
        }

        private void ReflectivelySetVisibilityFalse(RenderingExtension extension)
        {
            FieldInfo info = extension.GetType().GetField("m_serverExtension",
                                                          BindingFlags.NonPublic
							| BindingFlags.Instance);
            if (info != null)
            {
                Extension rsExtension = info.GetValue(extension) as Extension;
                if(rsExtension != null)
                {
                    rsExtension.Visible = false;
                }
            }
        }
    }
}

I really hope Microsoft includes this functionality in the next release of Reporting Services. It would be really quite simple to include it in the graphical report designer and avoid this nasty reflection hack entirely. At the very least, the sealed RenderingExtension class could have a mutable “Visible” property, rather than the read-only property it has now.

33 Comments »

mike on April 30th 2007 in .NET

33 Responses to “Disabling Export Formats in Reporting Services”

  1. AP responded on 26 Feb 2008 at 1:40 pm #

    Do you notice other rendering properties on the report getting messed up when you try this?

    We are seeing problems with the dock attribute specifically.

  2. mike responded on 26 Feb 2008 at 2:25 pm #

    We didn’t notice any problems but aren’t using that attribute. Maybe you could try reflectively setting that at the same time. I’d be very interested to find out how you do!

  3. kr responded on 21 May 2008 at 10:58 am #

    I can’t find the following namespace…

    using Microsoft.SqlServer.ReportingServices2005.Execution;

  4. kr responded on 21 May 2008 at 11:15 am #

    mike thanks for posting this as it seems this is exactly what we need… except I am not sure how to implement the code above.

    Thanks in advance!

  5. mike responded on 21 May 2008 at 12:02 pm #

    You need to add a reference from your project to the following DLLs:

    Microsoft.ReportViewer.Common.dll
    Microsoft.ReportViewer.WebForms.dll

    Then the using statement will work correctly.

  6. kr responded on 21 May 2008 at 2:20 pm #

    milke, thanks for the help. I am able to successfully build, but now when I debug the code info is always null in:

    “FieldInfo info = extension.GetType().GetField(“m_serverExtension”,
    BindingFlags.NonPublic
    | BindingFlags.Instance);
    if (info != null)”

    extension.GetType().GetField(“m_serverExtension”) is always null…

    any ideas?

    Your help is very much appreciated!!

  7. kr responded on 21 May 2008 at 4:57 pm #

    all i have from the above code is

    public void DisableUnwantedExportFormats()
    {
    foreach(RenderingExtension extension in MyReportViewer.serverReport.ListRenderingExtensions())
    {
    if(extension.Name == “XML” || extension.Name == “IMAGE”
    || extension.Name == “MHTML”)
    ReflectivelySetVisibilityFalse(extension);
    }
    }

    private void ReflectivelySetVisibilityFalse(RenderingExtension extension)
    {
    FieldInfo info = extension.GetType().GetField(“m_serverExtension”,
    BindingFlags.NonPublic
    | BindingFlags.Instance);
    if (info != null)
    {
    Extension rsExtension = info.GetValue(extension) as Extension;
    if(rsExtension != null)
    {
    rsExtension.Visible = false;
    }
    }

    I have this code in my codebehind on the same page as my reportviewer. Onload for my reportviewer I call DisableUnwantedExportFormats

    I have also ensured that my processingmode is remote so that MyReportViewer is using ServerReport instead of LocalReport…

    Am I on the right track? I am still getting null for the ”m_serverExtension” field.

    Thanks in advance for any and all help.

  8. dilip responded on 02 Jul 2008 at 7:11 am #

    I have the same situation , i am trying to disable the pdf and I am still getting null for the ”m_serverExtension” field. What is this ”m_serverExtension” field.

  9. mike responded on 02 Jul 2008 at 11:19 am #

    The code I included only works for Reporting Services 2005, and quite possibly only for a particular service pack or release of Reporting Services. The code uses reflection to directly manipulate the innards of the Reporting Services ReportViewer.

    Check your DLL versions, I am using the following:

    Microsoft.ReportViewer.Common.dll 8.0.50727.42
    Microsoft.ReportViewer.WebForms.dll 8.0.50727.42

  10. Chuck Schumacher responded on 29 Aug 2008 at 3:33 pm #

    Thanks for the extremely useful code sample.

    My client decided about a year ago to just allow export to PDF, which I managed to do via rsReportServer.config, but now they’ve decided that their system administrator — but not the other users — needs to be able to export to EXCEL and CSV, so I adapted your solution to solve the problem.

    All of our report viewer pages are based on the same master page, so I added a web.config entry for each defined role, listing the allowable export formats, and then added a couple of new methods to the master page, and a call to SetExportFormats() in Page_Load:

    protected void SetExportFormats()
    {
    StringBuilder _userFormats = new StringBuilder();
    string _roleFormats;
    //UserRole is an enum with a member for each
    //defined role. GetUserRoles() returns the
    //UserRole members that apply to the current user
    foreach (UserRole _userRole in GetUserRoles()
    {
    _roleFormats = ConfigurationManager.AppSettings["ExportFormats_" + _userRole.ToString()];
    if (!String.IsNullOrEmpty(_roleFormats))
    {
    _userFormats.Append(_roleFormats + “;”);
    }
    }
    string _visibleFormats = _userFormats.ToString();
    foreach (RenderingExtension _extension in rptReportViewer.ServerReport.ListRenderingExtensions())
    {
    SetRenderingExtensionVisibility(_extension, _visibleFormats.Contains(_extension.Name));
    }
    }
    }

    protected void SetRenderingExtensionVisibility(RenderingExtension _extension, bool _isVisible)
    {
    if (_extension.Visible != _isVisible)
    {
    FieldInfo _fieldInfo = _extension.GetType().GetField(“m_serverExtension”, BindingFlags.NonPublic | BindingFlags.Instance);
    if (_fieldInfo != null)
    {
    Microsoft.SqlServer.ReportingServices2005.Execution.Extension _rsExtension = _fieldInfo.GetValue(_extension) as Microsoft.SqlServer.ReportingServices2005.Execution.Extension;
    if (_rsExtension != null)
    {
    _rsExtension.Visible = _isVisible;
    }
    }
    }
    }

    After I added the references to the two assemblies mentioned in your response to another visitor, it works as expected and we’re prepared to handle any future changes of heart. Note, though, that I had to qualify Extension with the namespace rather than putting it in a using statement to avoid complaints about ambiguous definitions of ReportParameter, which is referenced elsewhere on the master page.

    Thought you might like to see how your solution has evolved.

    Chuck Schumacher
    BizWare Consulting Services
    Marblehead, MA

  11. mike responded on 31 Aug 2008 at 9:42 am #

    Hi Chuck, thanks for letting me know that you found the code useful and have adapted it for your purposes! It’s great to hear when someone finds something useful — I’m making it my mission in life to be in the top 10 Google search for stuff that’s taken me too long to figure out!

  12. Frank responded on 23 Sep 2008 at 9:23 am #

    Thanks for the insight and code snippets. This really helped me out a lot.

  13. Sunil responded on 29 Oct 2008 at 7:23 pm #

    Nice workaround. But unfortunately “m_serverExtension” has been removed in Reporting Services 2008 from the ReportExtension class. Any other way of doing the same?

  14. mike responded on 30 Oct 2008 at 11:42 am #

    Hi Sunil. I haven’t looked at RS 2008, but I’m not surprised the internals have changed. Maybe there’s now an official way to select export formats on a per-report basis.

  15. ravi raiya responded on 16 Jan 2009 at 4:50 am #

    hi dear,,,

    i m using local report of microsoft report server in vs2008. i just want to ristrict user not to export data in excel. i tried it many ways but all fail can u help doing this……..

    need reply urgently………..

    thanx in advance

  16. mike responded on 16 Jan 2009 at 9:33 am #

    Hi Ravi,

    Unfortunately this technique only works with Reporting Services 2005, I haven’t updated it for 2008. If you wish to disable Excel export you can still do this across the entire Reporting Services server, but this will disable Excel for all reports on the server, not just a specific report.

    You will need to modify the Render section in your Reporting Services configuration file. MSDN has more information here: http://msdn.microsoft.com/en-us/library/ms156281.aspx

  17. Svapneel responded on 03 Feb 2009 at 7:27 am #

    Hi,

    Thanks it worked like magic. I was using version 8.0.0.0 of report viewr common and webforms and it worked.

    To be honest I do not fully understand the solution but it works.

    Thanks again.

  18. Giulliano Dias responded on 28 Apr 2009 at 9:53 am #

    Mike,

    I worked with a version 9.0.0.0 and I found a lot of problems. I solved these problems with the code below:
    public void DisableUnwantedExportFormats()
    {
    foreach (RenderingExtension extension in serverReport.ListRenderingExtensions())
    {
    if (extension.Name == “XML” || extension.Name == “IMAGE” || extension.Name == “MHTML”)
    {
    ReflectivelySetVisibilityFalse(extension);
    }
    }
    }

    private void ReflectivelySetVisibilityFalse(RenderingExtension extension)
    {
    FieldInfo info = extension.GetType().GetField(“m_isVisible”,
    BindingFlags.NonPublic | BindingFlags.Instance);

    if (info != null)
    {
    info.SetValue(extension, false);
    }
    }

    // regards.

  19. Jon responded on 15 May 2009 at 4:57 pm #

    I tried below code in my ReportViewer page, but does not work. Please help. Thanks,

    foreach (RenderingExtension extension in ReportViewer1.ServerReport.ListRenderingExtensions())
    {
    if (extension.Name == “XML”)
    {
    FieldInfo info = extension.GetType().GetField(“m_isVisible”, BindingFlags.NonPublic | BindingFlags.Instance);
    if (info != null)
    {
    info.SetValue(extension, false);
    }
    }

    }

  20. mike responded on 18 May 2009 at 8:34 am #

    If you’re using Reporting Services with a DLL version of 9.0.0.0 (2008?) try Giulliano’s code snippet instead. My code example only works with Reporting Services 2005.

  21. [c#] Microsoft Report Viewer - Forum Fachinformatiker.de responded on 07 Aug 2009 at 1:30 am #

    [...] f

  22. Rob Kostecki responded on 11 Nov 2009 at 1:09 pm #

    I stumbled across similar challenge today using VS 2008 and SQL 2005 (9.00.4035.00). I found out that the “m_serverExtension” actually does not exists nor “Visible”. So just for a quick reference please find the code below.
    Bear in mind you will have to reference System.Reflection namespace. Also using Microsoft.SqlServer.ReportingServices2005.Execution namespace is not required nor Microsoft.ReportViewer.Common.dll assembly ref.

    public void DisableUnwantedExportFormats()
    {

    FieldInfo info;

    foreach (RenderingExtension extension in rvMain.ServerReport.ListRenderingExtensions())
    {
    if (extension.Name != “PDF” && extension.Name != “EXCEL”) // only PDF and Excel – remove the others
    {
    info = extension.GetType().GetField(“m_isVisible”, BindingFlags.Instance | BindingFlags.NonPublic);
    info.SetValue(extension, false);
    }

    if (extension.Name == “EXCEL”) // change “Excel” name on the list to “Excel 97-2003 Workbook”
    {
    info = extension.GetType().GetField(“m_localizedName”, BindingFlags.Instance | BindingFlags.NonPublic);
    if (info != null) info.SetValue(extension, “Excel 97-2003 Workbook”);
    }
    }
    }

    Hope this helps!

  23. Chad responded on 28 Dec 2009 at 2:52 pm #

    I am working for a company that has Reporting Services 2008, SQL SERVER 2008 and develops with VB. Here is the converted VB code.

    Public Class ServerReportDecorator
    Private ReadOnly serverReport As ServerReport

    Public Sub New(ByVal reportViewer As ReportViewer)
    Me.serverReport = reportViewer.ServerReport
    End Sub

    Public Sub New(ByVal serverReport As ServerReport)
    Me.serverReport = serverReport
    End Sub

    Public Sub DisableUnwantedExportFormats()
    For Each extension As RenderingExtension In serverReport.ListRenderingExtensions()
    If extension.Name = “XML” Or extension.Name = “IMAGE” Or extension.Name = “MHTML” Or extension.Name = “EXCEL” Or extension.Name = “WORD” Then
    ReflectivelySetVisibilityFalse(extension)
    End If
    Next
    End Sub

    Private Sub ReflectivelySetVisibilityFalse(ByVal extension As RenderingExtension)
    Dim info As FieldInfo = extension.GetType().GetField(“m_isVisible”, BindingFlags.NonPublic Or BindingFlags.Instance)

    If Not info Is Nothing Then
    info.SetValue(extension, False)
    End If
    End Sub
    End Class

  24. hellbinder responded on 09 Sep 2010 at 1:50 pm #

    I love you! This is what I needed for at least plan B. I am actually trying to check if the report exceeds the 256 column, is that possible? Because I want to disable the export option if it does exceed the column count of 256.

  25. chenman responded on 17 Feb 2011 at 8:55 am #

    Thanks you all for this wonderful solution. I had the similar issue as Chad. We have Reporting Services 2008, SQL SERVER 2008 R2, so Chad’s solution worked out great for me.
    Chad: I have a quick question, what was the change that you made to your web.config (formats to disable).

  26. sipho responded on 02 Mar 2011 at 11:41 pm #

    Thanks, it really helped me as well. It was easy to implement.

  27. whizkidguys responded on 03 Jun 2011 at 4:10 am #

    I’ve tried by adding your method DisableUnwantedExportFormats() for hiding Export to Excel option. When report loaded first time the excel option not getting visible.

    However, When I used to call the same method inside of Drillthrough() event “Excel” & PDF option getting visible in Export controls dropdown. I’ve tried by calling your method in the first statement of my Drillthrough() event,(like what I used in Page load method).

    Please let me know, How can I hide the excel option in Drillthrough() event of Reportviewer.

  28. Luigi responded on 10 Jun 2011 at 2:35 pm #

    I wish to know how i should invoke the assembly code in the Visual Report Designer (MSDev), or implement this solution, someone says that in the Load Event, but i dont know exactly how is it !. Thanks in advance ..

  29. DABOS responded on 06 Sep 2011 at 9:14 am #

    Really good solution Thank you, I hope I will collaborate soon.

  30. Rup responded on 09 Jan 2012 at 2:29 pm #

    is it possible to add close button or close option on Report Viewer bar.

  31. oche responded on 01 Apr 2012 at 8:52 pm #

    thank you very much for Giulliano Dias, I’m using version 9.0.0.0 too
    it’s really a good solution for my problem :D

  32. Sandeep responded on 27 Aug 2013 at 1:30 am #

    Mike you are successful in your mission of life. You are now in the top of the google search, for this disabling of unwanted report format querry !! :)

  33. Baju batik modern responded on 09 Oct 2013 at 2:13 am #

    Hi there, just wanted to say, I loved this article. It was inspiring.

    Keep on posting!

Trackback URI | Comments RSS

Leave a Reply