Adding custom code to Local Reports in Visual Studio.NET 2005 (Problems & Solutions)


If you are one of the people who used and enjoyed SQL Server Reporting Services (SSRS) in SQL 2000 and you wanted to use it in your windows/web applications without the server side components (just like what you are doing with Crystal Reports). So you would be much exited about the new ReportViewer Controls. ReportViewer controls are two controls for Windows and Web applications that can either show reports produced by SQL Server Reporting Services or process and render reports locally.


 


These reports are called Local Report and it's intended to provide reporting features without SSRS. You can use them without having a license for SSRS but be aware that you would lose some features like



  • Report parameters in client report definitions (.rdlc) do not map to query parameters. There is no parameter input area in a client report definition that accepts values that are subsequently used in a query.

  • Client report definitions do not include embedded query information. You must define data sources that return ready-to-use data for the report. So you have to provide a DataSource for your report like a DataSet, DataTable…

  • Browser-based printing through the RSClientPrint ActiveX control is not available for client report definitions that run in the ReportViewer Web server control. The print control is part of the report server feature set.

  • You would loose all collaboration activities of SSRS like scheduling to send reports to some users at specific time

 


I used ReportViewer for Windows forms in small report in which I had to add custom code in it and I had some problems that I would like to share with you solutions for them.


First we would go quickly through the process of creating simple report as following:


1)      Create a new windows forms project and open its form. Drag the ReportViewer control from the Data tab as shown in the image below


2)      Use the smart tag tasks to dock the report in all the form (you can use properties window as well). Then from the smart tag choose "Design new report". If you didn't see this option you can simply create new report. From solution explorer, right click on the project name then choose "add new item" then choose report.


3)      The report file would have the extension "rdlc" not "rdl" as it would be in server reports.


4)      Local Reports need to have a data source so go to Data Sources window and create your data source (let's say that it will get all Category name and description from categories table in Northwind)


5)      From the ToolBar window, drop a table inside the report


6)      From the Data Source window, drag & drop the CategoryName and Description fields to the details row of the table. Now you finished creating the report. Let's bind it to the ReportViewer


7)      Return back to the ReportViewer and from the smart tag menu choose, select your report name from the drop down menu.


8)      Run the application.


 


Now you have the report. Let's go to add custom code to the report.


 


Why would you add custom code?


You may want to add custom code to the report to do more actions than what's provided with the report functions. So it gives you a base for extending your report. You may want to add custom code to implement simple string manipulation task or sophisticated data access manipulation.


 


Cod added to Local Report can be one of two types:


            Embedded Code: Added directly inside the rdlc file. If you open the file in notepad, you can see the code inside the <Code> tag.


            Custom Assemblies: You can add a reference in external assembly and use functions inside it.


 


How to add a custom code in a local report?


According to MSDN library, you add it as following:


Embedded Code:



  1. On the Report menu, click Report Properties.

  2. On the Code tab, in Custom code, type the code.

Custom Assemblies:



  1. On the Report menu, click Report Properties.

  2. On the References tab, do the following:

  3. In References, click the add (...) button and then select or browse to the assembly from the Add Reference dialog box.

  4. In Classes, type name of the class and provide an instance name to use within the report. That's in the case of instance members, in the case of static (shared in VB) members, you don't need to add anything in Classes.

 


What's the code that I can add?


You can add class members only (properties, methods, fields) but you can't add classes because these members are encapsulated in a class at runtime, this class called Code class.


 


Take a look at this code snippet.


 


Public ReadOnly Property getSomeData() As String


        Get


            Return sharedMember


        End Get


    End Property


 


    Dim sharedMember As String = "Omar"


 


    Public Function toUpperCase(ByVal s As String)


        Dim conn As New System.Data.SqlClient.SqlConnection()


        Return s.toUpper()


    End Function


 


You can use this code inside a textBox or a table column as following =Code.toUpperCase(Code.getSomeData)


 


What are the namespaces that I can use inside my custom code?


All .NET namespaces can be used inside your custom code but be aware that by default only Microsoft.VisualBasic, System.Convert, and System.Math namespaces are referenced inside your reporting custom code.


 


Now let's jump into the problems.


 


Adding code that uses types that are not in these namespaces (Microsoft.VisualBasic, System.Convert, and System.Math)


Let's say that you are using a code that access SQL Server database to get some data to use it inside your report. You are using SqlConnection in your code. You would receive an error like this


There is an error on line 9 of custom code: [BC30002] Type 'System.Data.SqlClient.SqlConnection' is not defined.


Because System.Data.SqlClient resides in the System.Data.dll assembly and this assembly is not referenced by default by the report custom code. To solve this problem you need to add a reference to the System.Data.dll assembly in the References tag in the report properties window.


But this is not the end of the story; you would face another problem which described in the next step


 


How to make an assembly trusted for your report code


Because Local Reports like SQL Server Reporting Services reports are written using open format (Report Definition Language (RDL)). Any user can add any code or reference any assembly from your rdl file at the production environment which would cause a BIG security hole. You need to mark these assemblies as trusted inside your Windows Application code. Or you would get an error like this


The report references the code Module 'System.Data, Version=2.0.0.0, Culture=neutral, Publickey Token=b77a5XXXXXXXX', which is not a trusted assembly


 


You need to use the AddTrustedCodeModuleInCurrentAppDomain method of the LocalReport class. You can add the following line at the Form_load event handler of your windows application.


 


this.reportViewer1.LocalReport.AddTrustedCodeModuleInCurrentAppDomain("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");


 


And again it's not the end of the story; you will face another problem ;). Please be patient with me because I faced all these problems sequentially and I didn't find any resources to help me.


 


What are the Code Access Security (CAS) permissions assigned to any code running inside LocalReport by default


By default the only permission bound to the code running inside the LocalReport is ExecutePermission So your code can't access file system, databases, registry… unless you give it explicitly the required permissions.


For example, if you are trying to connect to a database from your code, you will get this error


Request of the permission of type 'System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKey Token=b77a5c561934e089' failed.


 


To give the assemblies running in the report the appropriate permissions, you need to use the ExecuteReportInCurrentAppDomain Method of the LocalReport class. Which causes the expressions in the report to be executed inside the current appDomain instead of executing them in a sandbox.


 


The ExecuteReportInCurrentAppDomain method takes one parameter of the type Evidence.


In the following example I'm using the evidence associated with my current appDomain so the report code will have all permissions that I have in my application


 


this.reportViewer1.LocalReport.ExecuteReportInCurrentAppDomain(AppDomain.CurrentDomain.Evidence);


 


By working on these steps, your code will run smoothly inside your report.


 


 


For the people who are trying to move their code in separated assembly and reference it from their report, they would face another problem.


If you are following the steps mentioned in MSDN regarding how to reference custom code (mentioned above). You will end up with this message


Error while loading code module: ‘ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. Details: Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.


 


After a lot of trials with this error, I found that I have to do the following.



  1. Select the report file from Solution Explorer, Go to Properties Window and change its BuildAction to Content

  2. Set Copy to output Directory property to Copy always or Copy if newer

  3. In the form designer class (the partial class created by Visual Studio according to naming schema <FormName>.Designer.CS or <FormName>.Designer.VB) replace the line which instruct the ReportViewer to load the report file from resource file with another line that instruct the ReportViewer to load the report from current directory.

  4. So this line

this.reportViewer1.LocalReport.ReportEmbeddedResource = "testLocalReport.Report1.rdlc";



  1. With this line

this.reportViewer1.LocalReport.ReportPath = "Report1.rdlc";



  1. Copy the dll that you are referencing to the Debug or Release directory of your application

  2. Make the line that executes the report in the current appDomain first, then add the lines that trust the referenced assembly and all assemblies referenced by this assembly (see above)

 


I hope this would help you to really enjoy VS 2005 features


 


//Mohamed


 


 

Comments (70)

  1. Sazzad says:

    being a long time access reports user, i am missing the "OnFormat, OnPrint etc.." report events which is not available in reporting services.

    anyone knows how to overcome this limitation of reporting services ??

  2. Mohamed says:

    Hello Sazzad,

    There are plenty of useful events of the ReportViewer control. Please take a look at this article http://msdn2.microsoft.com/en-us/library/ms255387.aspx

  3. Eran says:

    Great Article !

    Thank You 🙂

  4. Simple as usual, full of data as usual too, so lovely blog contains nice articles with easy implementation, I know I have not been taking too many looks over your blog, but It is really nice. Good Luck with it.

  5. Graham Angell says:

    After many frustrating hours trying to get a custom assembly to work with ReportViewer I found your blog.  Everything now works fine.  My sincere thanks!

  6. umangi Shah says:

    I have separated assembly and reference it from my report and I get following error.

    Error while loading code module: ‘ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. Details: Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

    you have mentioned following steps

    Select the report file from Solution Explorer, Go to Properties Window and change its BuildAction to Content

    Set Copy to output Directory property to Copy always or Copy if newer

    In the form designer class (the partial class created by Visual Studio according to naming schema <FormName>.Designer.CS or <FormName>.Designer.VB) replace the line which instruct the ReportViewer to load the report file from resource file with another line that instruct the ReportViewer to load the report from current directory.

    So this line

    this.reportViewer1.LocalReport.ReportEmbeddedResource = "testLocalReport.Report1.rdlc";

    With this line

    this.reportViewer1.LocalReport.ReportPath = "Report1.rdlc";

    Copy the dll that you are referencing to the Debug or Release directory of your application

    Make the line that executes the report in the current appDomain first, then add the lines that trust the referenced assembly and all assemblies referenced by this assembly (see above)

    But When I click on rdlc file in solution explorer I don't see Build Action in Properties window. Do I miss something?

  7. Raja says:

    Hi Mohammad,

    Your article is awesome and solved some of the mysteries I had....But now I have a problem of running the report (I am not using reportviewer control) which uses a custom assembly which in turn uses a web service to get the information required. I was able to get the report working in the preview mode but when I actually run it, It gave the exact error which you were talking in step 2 (Request for the permission of type 'System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.). It would be great if you can suggest me a measure to solve this.

    Thanks in Advance,

    Raja

  8. Amy says:

    I have separated assembly and reference it from my report and I get following error.

    Error while loading code module: ‘ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. Details: Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

    Your solution below:

    -----------------------------------------

    For the people who are trying to move their code in separated assembly and reference it from their report, they would face another problem.

    If you are following the steps mentioned in MSDN regarding how to reference custom code (mentioned above). You will end up with this message

    Error while loading code module: ‘ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. Details: Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

    After a lot of trials with this error, I found that I have to do the following.

    Select the report file from Solution Explorer, Go to Properties Window and change its BuildAction to Content

    Set Copy to output Directory property to Copy always or Copy if newer

    In the form designer class (the partial class created by Visual Studio according to naming schema <FormName>.Designer.CS or <FormName>.Designer.VB) replace the line which instruct the ReportViewer to load the report file from resource file with another line that instruct the ReportViewer to load the report from current directory.

    So this line

    this.reportViewer1.LocalReport.ReportEmbeddedResource = "testLocalReport.Report1.rdlc";

    With this line

    this.reportViewer1.LocalReport.ReportPath = "Report1.rdlc";

    Copy the dll that you are referencing to the Debug or Release directory of your application

    Make the line that executes the report in the current appDomain first, then add the lines that trust the referenced assembly and all assemblies referenced by this assembly (see above)

    -----------------------------------------

    applies to windows application.  Does anyone know how to solve it for a web application?

  9. jholmes says:

    I have the same problem Raja has.  Any suggestions on fixing it?  It's driving me crazy, not to mention I can't get my report working.

  10. I got round the file not found error by placing the file in "C:Program FilesMicrosoft Visual Studio 8Common7IDE".  I still can't seem to reference the code, but this is a step closer.

    ttfn

    David

  11. Seato says:

    Bloody Brilliant! Been looking for this info for ages. It was doing my head in until I found this insightful post.

    Microsoft really suck with documentation on this Report stuff. Kodos to you for trawling through the code to get it work.

    Well done, and THANKS!

  12. Bob says:

    Anyone find solution for web apps yet?

  13. Chris says:

    What I would really like to do is refrerence some code in the current assembly instead of a custom assembly.  This would avoid all the nasty versioning issues that I think would come with a custom assembly.  Is this possible?  I am assuming not, since I have never seen it mentioned anywhere and I can't get it to work.  But I don't understand why it wouldn't be supported.

  14. Satish says:

    Excellent Article. Thanks a lot.

    Microsoft should learn something from this guy.

  15. diego pego says:

    Really great article. That helped a LOT. I'm thinking if Microsoft intended to made this cryptic... anyway, thanks again!!!

  16. brunelli says:

    Thank you Mohamed for the helpful post!

    If anybody accesses code from an custom assembly, don't forget to add the AllowPartialyTrustedCallers into the AssemblyInfo. If not, your report will run, but you may get an #Error where you use a method or member of the assembly.

    Found here, and very useful anyway....

    http://www.c-sharpcorner.com/UploadFile/balajiintel/CustomAssemblyinRS06302005081435AM/CustomAssemblyinRS.aspx?ArticleID=f3904516-e30a-401a-aa01-463636d78f18

  17. lsites says:

    How do you get ClickOnce to deploy the rdlc files if you put the reports into a separate assembly

  18. Jelle says:

    Hi,

    I have a working .exe with a report viewer with a custom dll to look up use a resource file so that I can have multiple languages in my reports. However, if I change this project to a class and use it from another .exe I get the next nasty error(s). Seems some permission problems.. I tried adding [assembly: AllowPartiallyTrustedCallers] to the custom assembly, but without success. Who can help me on this one?

    Jelle

    Microsoft.Reporting.WinForms.LocalProcessingException: An error occurred during local report processing. ---> Microsoft.Reporting.DefinitionInvalidException: The definition of the report 'Main Report' is invalid. ---> Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: An unexpected error occurred in Report Processing. ---> System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.

      at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)

      at System.Security.CodeAccessPermission.Demand()

      at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)

      at System.Reflection.Assembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, StackCrawlMark& stackMark)

      at System.Reflection.Assembly.LoadFrom(String assemblyFile, Evidence securityEvidence)

      at System.Activator.CreateInstanceFrom(String assemblyFile, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo)

      at System.AppDomain.CreateInstanceFrom(String assemblyFile, String typeName)

      at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName)

      at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName)

      at Microsoft.ReportingServices.Diagnostics.AssemblyLocationResolver.CreateResolver(AppDomain tempAppDomain)

      at Microsoft.ReportingServices.ReportProcessing.ReportCompileTime.ResolveAssemblylocations(StringList codeModules, CompilerParameters options, ErrorContext errorContext, AppDomain compilationTempAppDomain)

      at Microsoft.ReportingServices.ReportProcessing.ReportCompileTime.InternalCompile(Report report, AppDomain compilationTempAppDomain, Boolean refusePermissions)

      at Microsoft.ReportingServices.ReportProcessing.ReportCompileTime.Compile(Report report, AppDomain compilationTempAppDomain, Boolean refusePermissions)

      at Microsoft.ReportingServices.ReportProcessing.ReportPublishing.Phase3(ParameterInfoCollection& parameters, AppDomain compilationTempAppDomain, Boolean generateExpressionHostWithRefusedPermissions)

      at Microsoft.ReportingServices.ReportProcessing.ReportPublishing.CreateIntermediateFormat(CatalogItemContext reportContext, Byte[] definition, CreateReportChunk createChunkCallback, CheckSharedDataSource checkDataSourceCallback, PublishingErrorContext errorContext, AppDomain compilationTempAppDomain, Boolean generateExpressionHostWithRefusedPermissions, String& description, String& language, ParameterInfoCollection& parameters, DataSourceInfoCollection& dataSources, UserLocationFlags& userReferenceLocation, ArrayList& dataSetsName, Boolean& hasExternalImages, Boolean& hasHyperlinks)

      at Microsoft.ReportingServices.ReportProcessing.ReportProcessing.CompileReport(CatalogItemContext reportContext, Byte[] reportDefinition, CreateReportChunk createChunkCallback, CheckSharedDataSource checkDataSourceCallback, PublishingErrorContext errorContext, AppDomain compilationTempAppDomain, Boolean generateExpressionHostWithRefusedPermissions, String& reportDescription, String& reportLanguage, ParameterInfoCollection& parameters, DataSourceInfoCollection& dataSources, UserLocationFlags& userReferenceLocation, ArrayList& dataSetsName, Boolean& hasExternalImages, Boolean& hasHyperlinks)

      at Microsoft.ReportingServices.ReportProcessing.ReportProcessing.CreateIntermediateFormat(CatalogItemContext reportContext, Byte[] reportDefinition, CreateReportChunk createChunkCallback, CheckSharedDataSource checkDataSourceCallback, AppDomain compilationTempAppDomain, Boolean generateExpressionHostWithRefusedPermissions)

    The action that failed was:

    Demand

    The type of the first permission that failed was:

    System.Security.Permissions.FileIOPermission

    The first permission that failed was:

    <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    Read="C:WINDOWSassemblyGAC_MSILMicrosoft.ReportViewer.Common8.0.0.0__b03f5f7f11d50a3aMicrosoft.ReportViewer.Common.dll"

    PathDiscovery="C:WINDOWSassemblyGAC_MSILMicrosoft.ReportViewer.Common8.0.0.0__b03f5f7f11d50a3aMicrosoft.ReportViewer.Common.dll"/>

    The demand was for:

    <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    Read="C:WINDOWSassemblyGAC_MSILMicrosoft.ReportViewer.Common8.0.0.0__b03f5f7f11d50a3aMicrosoft.ReportViewer.Common.dll"

    PathDiscovery="C:WINDOWSassemblyGAC_MSILMicrosoft.ReportViewer.Common8.0.0.0__b03f5f7f11d50a3aMicrosoft.ReportViewer.Common.dll"/>

    The granted set of the failing assembly was:

    <PermissionSet class="System.Security.PermissionSet"

    version="1">

    <IPermission class="System.Security.Permissions.FileDialogPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    Access="Open"/>

    <IPermission class="System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    Allowed="ApplicationIsolationByUser"

    UserQuota="512000"/>

    <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    Flags="Execution"/>

    <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    Window="SafeTopLevelWindows"

    Clipboard="OwnClipboard"/>

    <IPermission class="System.Security.Permissions.SiteIdentityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    Site="tempuri.org"/>

    <IPermission class="System.Security.Permissions.StrongNameIdentityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    PublicKeyBlob="0000000000000000"

    Name="AdminUnit.application"

    AssemblyVersion="1.0.0.19"/>

    <IPermission class="System.Security.Permissions.UrlIdentityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    Url="http://tempuri.org/AdminUnit.application"/&gt;

    <IPermission class="System.Security.Permissions.ZoneIdentityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1"

    Zone="Internet"/>

    <IPermission class="System.Drawing.Printing.PrintingPermission, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

    version="1"

    Level="SafePrinting"/>

    <IPermission class="System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

    version="1">

    <ConnectAccess>

    <URI uri="(http|https)://tempuri.org/.*"/>

    </ConnectAccess>

    </IPermission>

    </PermissionSet>

  19. Jelle says:

    it seems that I have my report viewer installed on D: and not in C: so in the C:windowsassembly where report viewer is looking by default is maybe the problem. How do I move my reportviewer to the GAC of the C?

  20. Jelle says:

    You have to provide the right path to the report:

    this.Viewer.LocalReport.ReportPath = Environment.CurrentDirectory + @"" + reportToLoad + ".rdlc";

    this.Viewer.ProcessingMode = ProcessingMode.Local;

               this.Viewer.LocalReport.ExecuteReportInCurrentAppDomain(AppDomain.CurrentDomain.Evidence);

               this.Viewer.LocalReport.ReportPath = Environment.CurrentDirectory + @"" + reportToLoad + ".rdlc";

               FileIOPermission filePerm = new FileIOPermission(FileIOPermissionAccess.Read, this.Viewer.LocalReport.ReportPath);

               filePerm.Assert();

               this.Viewer.LocalReport.AddTrustedCodeModuleInCurrentAppDomain(System.Reflection.Assembly.GetAssembly(typeof(GDS.User.WinLanguage)).FullName);

               this.Viewer.LocalReport.DataSources.Clear();

               foreach (System.Data.DataTable _dataTable in ReportDataSet.Tables)

               {

                   this.Viewer.LocalReport.DataSources.Add(

                       new ReportDataSource(ReportDataSet.DataSetName + "_" + _dataTable.TableName, _dataTable));

               }

  21. Great article!!! A very good exam of an interesting and very useful tool... Thank you!!!

  22. Sebastian says:

    Great post!, but what about localization? How can I localize my column headers?

  23. Pradeep says:

    Hi

    I have a problem in Printing Report from ReportViewer. If I print the report, when it is in NORMAL LAYOUT...it is not getting printed. But if I print the same by setting PRINT LAYOUT...coming good.

    Is there any way to show the report in PRINT LAYOUT by default? OR Is there any way to set the LAYOUT mode programaticaly?

    Thank you

    Pradeep.

  24. Bruno says:

    This worked fine for me untill I installed the SP1 for Visual Studio. Now I got back the "Error while loading code module: ‘ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. Details: Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."-Error. I am still investigating. Any soloution?

  25. Gancy says:

    Very nice article.  But I need to know how to use custom assemblies on web based report rendering.  My custom assembly need to access reportserver.exe.config file, which result sin FileIO security exception.  I am sure some one must have done this before.  

  26. Sebastian says:

    Hey dude, great article.

    For those having the "Error while loading code module:" error in web applications, try installing VS2005 SP1. But after that you win reports projects will have that error according to this:

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1099668&SiteID=1

    Still looking for the solution...

  27. M$ says:

    Is it possible to convert rdl to rdlc and render the report at run time ?

  28. M$ says:

    Is this the only way to convert RDL to RDLC and could this be done at run-time ?

    RDL-to-RDLC Conversion

    When converting a .rdl file to .rdlc format, you must manually replace the data source and query information in the report definition with data constructs provided in your application.

      1.

         Rename the .rdl file to use the .rdlc file extension.

      2.

         In Visual Studio 2005, open the solution or project that will contain the report.

      3.

         Create or add the dataset that defines the data you want to use to your projector solution. For more information, see Creating Data Sources for a ReportViewer Report.

      4.

         On the Project menu, click Add Existing Item and then select the .rdlc file that you created in the first step.

      5.

         In the project, open the form or Web page that will contain the report.

      6.

         From the Toolbox, in the Data group, drag a ReportViewer control onto the form or Web page.

      7.

         In the ReportViewer Tasks smart tags panel, in Choose Reports, select the .rdlc file to use with the control.

      8.

         In the ReportViewer Tasks smart tags panel, in Choose Data Sources, select the dataset you want to use. The dataset object, binding source object, and table object will appear at the bottom of the workspace. For more information about updating data source references, see Updating and Rebinding Data Source References.

      9.

         Save all files, and then build or deploy the project to verify that the report contains the data you expect.

  29. Vikas says:

    If you are trying to access a custom assembly code in the reports and if you are getting the following error.

    Error while loading code module: ‘ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. Details: Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

     Then copy the Custom Assembly dll into the following folder.

    PROGRAMFILESVisual Studio 8Common7IDEPublicAssemblies

    See the following post for more details.

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1099668&SiteID=1

    Good Post Mohamed 🙂

  30. Bogdan says:

    Great article!

    This report control is a mess and it feels just like no more than an “idea”.

    Thanks to this article and all comments I finally managed to run something...

    Here are few pointers for those trying to display images from DB on the report.

    In my example I used Categories table from Northwind DB

    Image control available for the report control needs raw bytes to be passed in Value property.

         Note: System.Windows.Forms.PictureBox.Image property uses Image class.

    Image.MIMEType=image/bmp

    Image.Source=Database

    Image.Value=Utils.Utils.GetRawBytes(Fields!Picture.Value)

    Where GetRawBytes() is a static method in a referenced assembly Utils

    using System;

    using System.Drawing;

    using System.IO;

    using System.Configuration;

    namespace Utils

    {

       public class Utils

       {

           public static byte[] GetRawBytes(byte[] bytes)

           {

               // remove OLE header if present

               MemoryStream ms = null;

               try

               {

       int offset = 0;

                // use offset=78 for Northwind DB

                   if (ConfigurationManager.AppSettings["ImageOffset"].ToString().Length > 0)

                       offset = Convert.ToInt32(ConfigurationManager.AppSettings["ImageOffset"]);

                   if (offset > 0)

                   {

                       ms = new MemoryStream(bytes, offset, bytes.Length - offset);

                       bytes = ms.ToArray();

                   }

               }

               catch (Exception ex)

               {

                   Console.WriteLine(ex.Message);

               }

               finally

               {

                   if (ms != null)

                   {

                       ms.Close();

                       ms = null;

                   }

               }

               return bytes;

           }

       }

    }

  31. Suri says:

    Print button is not visible when i use rdl files as local reports through report viewer.

    Print button is not displaying and only two types of export options.

  32. Pete says:

    Hi,

    Just sharing a "feature" on winform reportviewer which did cost a day to figure out:

    I got "Some parameters or crednetials have not been specified". Strange thing, I did not get them when running through visual studio (either debug or release), but ONLY when run apart from VS. (go figure that one).

    After working through tips here on the site, THANKS,  (a few I discovered the "hard way" already), I finally figured it and just wanted to share:

    First do a localreport refresh, than the viewer itself:

    reportViewer1.LocalReport.Refresh();

    reportViewer1.RefreshReport();

    For some reason I had it the other way around, resulting in that mysterious error, but not within VS environment.

    Cheers,

    Pieter

  33. Shane says:

    Thanks for the post.  What you can also do is add the copying of the dll to the PublicAssemblies folder to the post build event for the assembly in your code so you don't have to remember to do it after each build.  e.g.

    copy E:projectsvsdev<project>CommonbinDebugProject.Common.dll "C:Program Files (x86)Microsoft Visual Studio 8Common7IDEPublicAssemblies"

  34. John says:

    How do you format Boolean columns to display a checkbox?

  35. Monika Aleksieva says:

    John,

    You cannot display checkboxes. If you want to display boolean columns, you can add an image and specify image path depending on the value of your data. For example 1.gif (true) and 0.gif (false) can look like a box with or without a tick.

  36. Monika Aleksieva says:

    For web apps to work with local reports and custom assemblies that are NOT installed in GAC, you have to run Microsoft Report Viewer Redistributable 2005 SP1. This is available here - http://www.microsoft.com/downloads/details.aspx?FamilyId=35F23B3C-3B3F-4377-9AE1-26321F99FDF0&displaylang=en

  37. John says:

    I have a formula for column called %Diff to Goal

    =Iif(Fields!ThisYearActual.Value > 0 And Fields!ThisYearGoal.Value > 0,( (Fields!ThisYearActual.Value  -   Fields!ThisYearGoal.Value) /  Fields!ThisYearGoal.Value), 0 )

    What I really want is to check for values greater than NULL, but used "> 0" instead.

    But I do not see any options in the Edit Expression dialog box to check for Null values.

    At the moment, if ThisYearActual is > 0, but ThisYearGoal is Null, the ‘% Diff to Goal’ is displaying an ‘#Error’ message.

    Is there a better way to write this formula, and/or check for null values?

  38. Tom says:

    I have a report that is part of my project (is not in a DLL) so is there a way to access textboxes that I've placed on the report to populate with a value?  Or do I need to put my report in a seperate DLL?

    I guess the part that is confusing me is when you browse to add a reference.....is this referring to the fact that the report is in a DLL?

    Thanks and great blog

  39. Di says:

    I have a problem with deploying reports from Visual Studio where it is remembering an old user name to try to use for deploying - it does not have sufficient permissions.  Do you know how to force it to prompt for a user?   For deploying, we only need to supply a URL in the project properties.

  40. Di says:

    Excellent -solved my problem with the error.However, I am trying to use the custom code to create a comma delimited list of values from the row values in a table. I get the list accummulating correctly till the group footer where the list value is then empty.  The list is accummulated within my external class using calls on the detail line of the table.

    It appears that there is a separate instance being used for the level 1 grouper from the detail line grouper and thus when I call my external class to get the accumulated value, the result is empty.

    Any suggestions on how to overcome this would be greatly appreciated.

  41. Anthony Manvell says:

    Excellent, concise article. Very informative will save me hours of investigation. Many thanks.

  42. VinK says:

    Displaying checkboxes in microsoft reports is very simple and an interesting method can be found right here

    http://www.xhydra.com/dotnet/displaying-checkboxes-in-microsoft-reports.html

  43. dshah says:

    Thanks for this amazing blog.. i have visited this blog for the first time and I am fan of it now. This article is amazing.

    Thank you so much.

  44. Samee Qayum says:

    AS,

    I have used your solution but the problem of adding a data source name was not included - had to get from MS support.

    I still have the problem:

    T"he report references the code module 'System.Windows.Forms', which is not trusted"

    Can you help ?

    Regards

    Samee Qayum

  45. alexjoei says:

    Hello, good article, but i have donde all hte steps, and i still have the:

    "The report references the code module ‘System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’, which is not a trusted assembly".

    I have a report that in the 'Code' has a function that uses system.drawing, i write in my load event the two lines (AddTrustedCodeModuleInCurrentAppDomain, ExecuteReportInCurrentAppDomain)

    but it dont solves my problem,

    any idea please??

  46. Cesar says:

    Really thanks for this useful blog!! ^^

  47. Cesar says:

    And, ah. If you still are running problems with "no permission" message event after adding the AddTrustedCodeModuleInCurrentAppDomain and ExecuteReportInCurrentAppDomain, the error was gone when I inverted the order. So, you need to execute ExecuteReportInCurrentAppDomain first, then AddTrustedCodeModuleInCurrentAppDomain.

  48. Michael C says:

    And that does it!! Thanks Ceasar.  I inverted the AddTrustedCodeModuleInCurrentAppDomain and ExecuteReportInCurrentAppDomain and there you have it, my barcode generation code loaded.  Now just to get it to format the datastream.

    Now I have a solution to replace lovely Crystal Reports.

  49. jim hudson says:

    mohammed, you are the man. ever think about writing a book 😉

  50. Ravi says:

    Hi...

    I am having a report name "Report1.rdlc"

    Now,I want to add a textbox at runtime...How can i??

    Thanks in advance

  51. mojtaba says:

    Thank For Your Try And Soloution...

  52. I found a way to deal with the problem that Raja says above at:

    "http://blogs.msdn.com/mosharaf/archive/2005/12/20/LocalReportCustomCode.aspx#606223&quot;

    After a lot of checking, at last I found out that if you disable the "ClickOnce Security Settings" from the security section of properties of your project, it works fine. I don't know exactly why, but it works.

  53. sorry, in the previous comment that I posted, I typed an extra double quotation at the end of the link.

  54. TechSpoken says:

    Report Preprocessing: SQL Server Reporting Server Group PageTotals Walkthrough, Part I: the RDL and the Server

  55. sunu says:

    i have created a report rdlc and got connection to the database .... the databse has only two columns fname and lname...

    the query in the table adapter is:

    SELECT fname, lname FROM dbo.sunu  where lname=@lastname

    i have set a report parameter "lastname" also ..

    i have passed the parameter value as "s" through the set parameter method and obtained it in the report also as i can see the parameter printed on my report when it is rendered...

    but the data is not filtered based on lname="s"??

    any ideas as to what i am doing wrong??

  56. sunju says:

    one more thing .. iam not using reportviewer instead i am directly writing the report to a file

  57. Smith says:

    When i try to use your function toUpperCase i get the following error message:

    An error occurred during local report processing. Failed to load expression host assembly. Details: Parameter count mismatch.

    I double checked the parameters i`m passing to the method and cannot figure out where is the problem.

    Even on the most simple example like =Code.toUpperCase("aaa") i get the same message!

    Can you please give me some clue?

  58. uma says:

    hi how to display subtotal of previous page in the top of next page in rdlc report.

    Ex:

    page 1

    name acc bal

    a    6    10

    b     7    20

    sutotal    30

    page 2

    subtotal of first page 30

    name acc bal

    aa    6    10

    bb     9    60

    sutotal    70

    page 3

    subtotal of second page 30

    can anyone plz.. help me its urgent.

    Thanks in advance,

    uma

  59. Reference custom code assembly in ReportViewer control

  60. uma says:

    hi i am using this custom code to display subtotal of first page in the next page

     Public Double  P=0

     Public String Myfun(Double t)

    {

        P=t

        Return  P

       }

    and i am calling this fun in text box

    =Code.Myfun(Sum(Fields!OrderID.Value.ToString))

    =IIF(Code.P = 0,"",Code.P)

    but its giving these  errors

    Error 1 There is an error on line 1 of custom code: [BC30183] Keyword is not valid as an identifier. C:InetpubwwwrootWebSite5Report.rdlc 1

    Error 2 The Value expression for the textbox ‘OrderID_2’ contains an error: [BC30456] 'Myfun' is not a member of 'ReportExprHostImpl.CustomCodeProxy'. C:InetpubwwwrootWebSite5Report.rdlc 1

    Error 3 The Value expression for the textbox ‘textbox13’ contains an error: [BC30456] 'P' is not a member of 'ReportExprHostImpl.CustomCodeProxy'. C:InetpubwwwrootWebSite5Report.rdlc 1

    plz.. anyone can help me.

    thanks

    uma

  61. jemacc says:

    I am trying to add code to  to my report. I am not very familiar with referencing the assembly.  With the following code can you point me in the right direction as to how I would refrence the assembly and classes

    Function SetLanguage(ByVal value AS Object) As Object

    If value = "EUR"  

    Return "French"

    ElseIf value = "GBP"

    Return  "French"

    Else

    Return "French"

    End If

    End Function

  62. Chris Forbes says:

    Embedded or local reports: I shall test this in a WinForm application, but I can not get the report engine to see, "find",  a private assembly using the ReportViewer control and a local report (.rdlc) in a web application using SQLExpress unless I put the assembly into C:WindowsMicrosoft.Netframeworkv2.0.50727MyTestAssembly.dll (for example).  I have tried all of the above lines of code in my on_load routine and while the permissions problem is solved, finding the library is not, or at least not for web apps.

    If the system directory, .../v2.0.50727, is the only way, it won't fly.  System admins would have tripple kittens and frankly, I wouldn't blame them.  

    Also, it would be of very limited use to build libraries of functionality that could be used by Reports in WinForm applications, but not in Web applications.

    If there is a way to inform the Report engine from a web app where to look for the dll (it's plumb crazy that it doesn't at least look in current directory), I would love to hear about it.  Having said that, great blog!  Even the books I can find don't go into this much detail.

  63. AAA says:

    Do you know how to refer to the report parameters in the custom code

  64. Dilip M.D says:

    It worked for me with just first step. Thanks Mohamed.

  65. Re: your blog - good stuff!

    I am just getting into Microsoft Reports, initially doing reports for display in a reportviewer and using local mode rather than a server as part of a billing system I am building in VS2005 - the objective was to find a way to avoid endless hours of typing printdocument code and to take advantage of the

    PDF/Excel export feature. The learning curve got pretty steep when I started to do a report that would generate an invoice.

    Part of the complexity is due to the fact that the viewer will be used to display multiple reports.

    Hopefully the following code (triggered when a selection is made from a listbox) will be helpful in giving others who might be trying to do something similar not necessarily answers but instead insights into the process.

    There is a well documented problem when printing with the 2005 viewer. On some

    printers - including both my Canon printers - the margins get messed up unless

    the margins are set to .5in or more. The easy solution is to just set the margins

    to .5in and accept the fact that they're wider than we'd prefer.

    I would agree with the observation that Reports and the Reportviewer are works in progress but that seems to be the case with lots of Microsoft stuff - seems like whenever we want to do something that goes beyond basic functionality that things get ugly. I wonder if any of the people who develop things there ever try to put them to use in the real world.

    My comments in the code are notes to myself to remind me what I did and why.

               switch (listBoxReportList.Text.ToString())

               {

              //You have to manually set the datasource when doing the subreport as below

               //We want to display different reports in the same report viewer.

               //The tricky part is that we build the reports in the development environment

               //using the PMABillingDataSet but the program actually uses an instance of it called pmaBillingDataSet1.

               //After we've built the report, the we need to go into the rdlc file code for the report using the XML editor

               //and change the PMABillingDataSet references to pmaBillingDataSet1 to get the thing to work.

               //Perhaps the answer is to pass the datasetname as a parameter.

               //In the report viewer, we can't use embedded resource value because it would lock in the data source so we need to use

               //file path to get the report. In the development environment, the path is bindebugReports.

               //In the code below, note that the datasource(ReportDataSource - "pmaBillingDataSet1_Customer") values have to match

               //to match the values in bindingSourceCustomer.

               //Also note that if you do not uses the Reset method as shown below, the viewer holds the reference to the last

               //instance used and doesn't do the new report because it's trying to use the old datasource. Yuk!

               //Also note that after we've done it all, we have to call RefreshReport to get the report to display.

               //Unless the following is done, the reportviewer will not display a report containing subreports

               //The standard approach include private void SubreportBasicInfoEventHandler(object sender, SubreportProcessingEventArgs e) to handle the event

               //this.reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(SubreportBasicInfoEventHandler);

               //it and call it in Form_Load. For the moment, I created the handler here.

       //Note that the sequence in which things happen needs to be right.

                   case "Customer List":

                       System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;

                       buttonShowReport.BackColor = System.Drawing.Color.Chocolate;

                       listBoxReportCustomer.SelectedIndex = 0;

                       listBoxReportMonth.SelectedIndex = -1;

                       listBoxReportYear.SelectedIndex = -1;

                       reportViewer1.LocalReport.DataSources.Clear();

                       reportViewer1.Reset();

                       reportViewer1.LocalReport.ReportPath = Application.StartupPath + @"ReportsReportCustomerList.rdlc";

                       ReportDataSource mydatasource = new ReportDataSource("pmaBillingDataSet1_Customer", bindingSourceCustomer);

                       reportViewer1.LocalReport.DataSources.Add(mydatasource);

                       reportViewer1.RefreshReport();

                       System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;

                       break;

                   case "Current Invoice":

                       System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;

                       buttonShowReport.BackColor = System.Drawing.Color.Chocolate;

                       listBoxReportCustomer.SelectedIndex = 0;

                       listBoxReportMonth.SelectedIndex = -1;

                       listBoxReportYear.SelectedIndex = -1;

                       reportViewer1.LocalReport.DataSources.Clear();

                       reportViewer1.Reset();

                       reportViewer1.LocalReport.ReportPath = Application.StartupPath + @"ReportsReportInvoiceContainer.rdlc";

                       reportViewer1.LocalReport.EnableExternalImages = true;

                       //the following values are for test purposes only

                       //if the parameters are left empty, we get errors

                       CompanyName = "Test Company Name";

                       CompanyAddress = "1000 Main St.";

                       InvoiceImage1 = Application.StartupPath + "/images/InvoiceImage1.jpg";

                       InvoiceImage2 = Application.StartupPath + "/images/InvoiceImage2.jpg";

                       //This sets the string value for a parameter ("ParamaterName", value). The Parameter "CompanyNameParameter"

                       //is declared in the report as an empty parameter.

                       ReportParameter companynamevalue = new ReportParameter("CompanyNameParameter", CompanyName);

                       reportViewer1.LocalReport.SetParameters(new ReportParameter[] {companynamevalue});

                       ReportParameter companyaddressvalue = new ReportParameter("CompanyAddressParameter", CompanyAddress);

                       reportViewer1.LocalReport.SetParameters(new ReportParameter[] {companyaddressvalue});

                       //This parameter is used in the filter

                       ReportParameter invoiceidnumber = new ReportParameter("InvoiceIDNumberParameter", textBoxInvoiceNumber.Text.ToString());

                       reportViewer1.LocalReport.SetParameters(new ReportParameter[] {invoiceidnumber});

                       ReportParameter imagelogo1 = new ReportParameter("ImagePath1Parameter", InvoiceImage1);

                       reportViewer1.LocalReport.SetParameters(new ReportParameter[] { imagelogo1 });

                       ReportParameter imagelogo2 = new ReportParameter("ImagePath2Parameter", InvoiceImage2);

                       reportViewer1.LocalReport.SetParameters(new ReportParameter[] { imagelogo2 });

                       ReportDataSource mydatasourceinvoice = new ReportDataSource("pmaBillingDataSet1_InvoiceLineItem2008", bindingSourceInvoiceDetail);

                       reportViewer1.LocalReport.DataSources.Add(mydatasourceinvoice);

                       this.reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(SubreportInvoiceEventHandler);

                       reportViewer1.RefreshReport();

                       System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;

                       break;

  66. Yasser Ahmed says:

    Thanks for ur great effort >> I am working on web application and I have followed all your steps to add function in code to connect database and add the dll reference but i still get this error :There is an error on line 4 of custom code: [BC30002] Type 'SqlConnection' is not defined.

    My function is:

    Public Function TestConn(ByVal RevID As String, ByVal QstID As String, ByVal AnswID As String) As String

       Dim constr As String = "Data Source=THINKPADSQLEXPRESS;Initial Catalog=motorola;Integrated Security=SSPI"

       Dim ObjConn2 As SqlConnection = New System.Data.SqlClient.SqlConnection(constr)

       ObjConn2.Open()

       Dim strSQL As String = "SELECT COUNT(dbo.MotoDetails.AnswerID) AS AnswerCount FROM Dale_Eval INNER JOIN MotoDetails ON Dale_Eval.Rev_ID = MotoDetails.Rev_ID WHERE MotoDetails.QuestID =" + QstID + " AND Dale_Eval.Rev_ID = " + RevID + " AND MotoDetails.AnswerID = " + AnswID + ""

       Dim cmd As SqlCommand = New System.Data.SqlClient.SqlCommand(strSQL, ObjConn2)

       Dim dr As SqlDataReader

       dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)

       dr.Read()

       Dim TotlaAn As String = dr(0).ToString()

       dr.Close()

       Return TotlaAn

    End Function

  67. DarkAraym says:

    Thank you so much!!! I've been trying to do this for ages. For a while I was still getting the permission error, but thanks to Ceasar everything works great. AMAZING!

  68. Doug Tumeo says:

    I am creating reports in SSRS 2005 that will be displayed directly from ReportServer, not within an application. In this situation, do you know of a way to hide controls based upon whether the report is rendered on screen or printed. (I want to hide some controls on printed output.)

    Thanks in advance,

    Doug

  69. Great post, but I'm trying to use Code class after introduce a function in Code tab and it doesn't work:

    Code tab:

    public function Hello()as string

      return "Hello"

    end function

    Expression:

    =Code.   <---- And here it doesn't appear my function listed. Someone knows why? I'm gonna be crazy with this...

  70. en88 says:

    And, ah. If you still are running problems with "no permission" message event after adding the AddTrustedCodeModuleInCurrentAppDomain and ExecuteReportInCurrentAppDomain, the error was gone when I inverted the order. So, you need to execute ExecuteReportInCurrentAppDomain first, then AddTrustedCodeModuleInCurrentAppDomain.

    I still don't get the permission after switch the position of two statements. I'm using VS 2008, is this the reason why it doesn't work for me?

Skip to main content