Add An Assembly Reference To A Report
Add An Assembly Reference To A Report
(SSRS)
03/14/2017
2 minutes to read
Contributors
o
When you embed custom code that contains references to Microsoft .NET Framework
classes that are not in Math or Convert, you must provide an assembly reference to the
report so that the report processor can resolve the names. For more information,
see Add Code to a Report (SSRS).
To add an assembly reference to a report
1. In Design view, right-click the design surface outside the border of the report and
click Report Properties.
2. Click References.
3. In Add or remove assemblies, click Add and then click the ellipsis button to
browse to the assembly.
4. In Add or remove classes, click Add and then type name of the class and provide
an instance name to use within the report.
Note
Specify a class and instance name only for instance-based members. Do not
specify static members in the Classes list. For more information, see Custom Code
and Assembly References in Expressions in Report Designer (SSRS).
5. Click OK.
o all
In Reporting Services, you can write custom code for report item values, styles, and
formatting. For example, you can use custom code to format currencies based on locale,
flag certain values with special formatting, or apply other business rules that are in
practice for your company. One way to include this code in your reports is to create a
custom code assembly using the Microsoft .NET Framework that you can reference from
within your report definition files. The server calls the functions in your custom
assemblies when a report is run. Custom assemblies can be used to retrieve specialized
functions that you plan to use in your reports.
In This Section
o
o
o
all
To support the use of custom code assemblies in report definition files, two Report
Definition Language (RDL) elements are included in the RDL specification:
the CodeModules element and the Classes element.
The CodeModules element enables you to refer to managed code assemblies in report
expressions. CodeModules is a top-level element that contains the reference to the
assembly that you use in your report definition files to call specialized functions. An
entry in a report definition that supports the use of a custom assembly might look like
the following:
Copy
<CodeModules>
<CodeModule>CurrencyConversion, Version=1.0.1363.31103, Culture=neutral,
PublicKeyToken=null</CodeModule>
</CodeModules>
Instead of calling Load from your custom code, register your custom assemblies by
either manually adding CodeModule elements to your RDL file or by using
the References tab of the Report Properties dialog. For more information, see Custom
Code and Assembly References in Expressions in Report Designer (SSRS).
o all
Once you have created a custom assembly, made it available to Report Designer or the
report server, added the appropriate security policy, and added a reference to your
custom assembly in your report definition, you can access the members of the classes in
your assembly using report expressions. To refer to custom code in an expression, you
must call the member of a class within the assembly. How you do this depends on
whether the method is static or instance-based.
Calling Static Members from a Report Definition File
Static members belong to the class or type itself and not to an instantiated object. These
members can be accessed by directly calling them from the class. You should use static
members to call custom functions in a report whenever possible, because static
members perform best. To call a static member, you need to reference it as an
expression that takes the form =Namespace.Class.Method.
To call static members
To call a static member, set your expression equal to the fully qualified name of the
member, which includes the namespace, class name, and member name. The
following example calls the ToGBP method, which converts
the StandardCost field value from dollars to pounds sterling and displays it in a
report:
Copy
=CurrencyConversion.DollarCurrencyConversion.ToGBP(Fields!StandardCost.Va
lue)
Important Information Regarding Static Fields and Properties
Currently, all reports are executed in the same application domain. This means that
reports with user-specific, static data expose this data to other instances of the same
report. This condition might make it possible for the static data of one user to be
available to all users currently running a particular report. For this reason, it is highly
recommended that you not use static fields or properties in custom assemblies or in
the Code element; instead, use instance fields or properties in your reports. Static
methods can still be used, because they do not store state or data.
Calling Instance Members from a Report Definition File
If your custom assembly contains instance members that you need to access in a report
definition, you must add an instance name for your class to the report. You can add an
instance name for a class using the Code tab of the Report Properties dialog. For more
information about adding instances of classes to a report, see Custom Code and
Assembly References in Expressions in Report Designer (SSRS).
To call a static member, you need to reference it as an expression that takes the form
=Code.InstanceName.Method.
To call instance members
Copy
=Code.m_myDollarCoversion.ToEUR(Fields!StandardCost.Value)
o all
To deploy a custom assembly in SQL Server Reporting Services, place the assembly in
the application folders of both Report Designer and the report server. By default,
custom assemblies are granted Execution permission in Reporting Services. To grant
custom assemblies privileges beyond Execute permission, you will need to edit the
rssrvpolicy.config configuration file for the report server and the rspreviewpolicy.config
configuration file for the Report Designer preview window. Alternatively, you can install
your custom assembly in the global assembly cache (GAC).
Note
There are two preview modes for Report Designer: the Preview tab and the pop-up
preview window that is launched when your report project is started
in DebugLocal mode. The Preview tab executes all report expressions using
the FullTrust permission set and does not apply security policy settings. The pop-up
preview window is meant to simulate the report server functionality and therefore has a
policy configuration file that you or an administrator must modify to use custom
assemblies in Report Designer. This pop-up preview also locks the custom assembly.
Therefore, you need to close the preview window in order to modify or update your
custom assembly code.
To deploy a custom assembly in Reporting Services
1. Copy your custom assembly from your build location to the report server bin
folder or the Report Designer folder. The default location of the bin folder for the
report server is %ProgramFiles%\Microsoft SQL
Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer\bin. The
default location of the Report Designer is %ProgramFiles%\Microsoft Visual Studio
9.0\Common7\IDE\PrivateAssemblies.
Placing your custom assembly in the report server bin folder enables you to
publish reports that reference your custom assembly, and placing it in the Report
Designer folder enables you to run and debug reports that reference your custom
assembly in Report Designer.
If you need to grant your custom assembly code permissions beyond the default
execute permissions:
At some point, you may need to update a version of a custom assembly that is currently
being referenced by several published reports. If that assembly already exists in the bin
directory of the report server or Report Designer and the version number of the
assembly is incremented or changed in some way, the currently published reports will
no longer work properly. You will need to update the version of the assembly that is
referenced in the CodeModules element of the report definition and republish the
reports. If you know that you will frequently update a custom assembly and your
currently published reports need to reference the new assembly, you may want to
consider using the same version number across all updates of a particular assembly.
If you do not need your currently published reports to reference the new version of the
assembly, you can deploy your custom assembly to the global assembly cache. The
global assembly cache can maintain multiple versions of the same assembly, so that
your current reports can reference the previous version of your assembly and your newly
published reports can reference the updated assembly. Yet another approach would be
to set the binding redirect of the report server to force a redirect of all requests for the
old assembly to the new assembly. You would need to modify the report server
Web.config file and the report server ReportService.exe.config file. The entry might look
like the following:
Copy
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="myAssembly"
publicKeyToken="32ab4ba45e0a69a1"
culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0"
newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Using Strong-Named Custom Assemblies
03/14/2017
2 minutes to read
Contributors
o
o all
A strong name identifies an assembly and includes the assembly's text name, four-part
version number, culture information (if provided), a public key, and a digital signature
stored in the assembly's manifest. A strong name uniquely identifies an assembly to the
common language runtime (CLR) and ensures binary integrity.
Using AllowPartiallyTrustedCallersAttribute
To use strong-named assemblies with reports, you must allow your strong-named
assembly to be called by partially trusted code using the
assembly's AllowPartiallyTrustedCallers attribute. You can
use AllowPartiallyTrustedCallersAttribute to allow strong-named assemblies to be
called by Report Designer or the report server in report expressions. To allow partially
trusted code to call strong-named assemblies, add the following assembly-level
attribute to your assembly attribute file.
VBCopy
<assembly:AllowPartiallyTrustedCallers>
C#Copy
[assembly:AllowPartiallyTrustedCallers]
o all
By default, custom assembly code runs with the limited Execution permission set. In
some cases, you may wish to implement a custom assembly that makes secured calls to
protected resources within your security system (such as a file or the registry). In order
to accomplish this, you must do the following:
1. Identify the exact permissions that your code needs in order to make the secured
call. If this method is part of a Microsoft .NET Framework library, this information
should be included in the method documentation.
2. Modify the report server policy configuration files in order to grant the custom
assembly the required permissions. For more information about the security policy
configuration files, see Using Reporting Services Security Policy Files.
3. Assert the required permissions as part of the method in which the secure call is
made. This is required because the custom assembly code that is called by the
report server is part of the report expression host assembly, which runs
with Execution permission by default. The Execution permission set enables code
to run, but not to use protected resources.
4. Mark the custom assembly with AllowPartiallyTrustedCallersAttribute if it is
signed with a strong name. This is required because custom assemblies are called
from a report expression that is part of the report expression host assembly, which,
by default, is not granted FullTrust; thus it is a "partially trusted" caller. For more
information, see Using Strong-Named Custom Assemblies.
Implementing a Secure Call
You can modify the policy configuration files to grant your assembly specific
permissions. For example, if you were writing a custom assembly to handle currency
conversion, you might need to read the current currency exchange rates from a file. To
retrieve the rate information, you would need to add an additional security
permission, FileIOPermission, to your permission set for the assembly. You can make
the following additional entry in the policy configuration file:
Copy
<PermissionSet class="NamedPermissionSet"
version="1"
Name="CurrencyRatesFilePermissionSet"
Description="A special permission set that grants read access to my
currency rates file.">
<IPermission class="FileIOPermission"
version="1"
Read="C:\CurrencyRates.xml"/>
<IPermission class="SecurityPermission"
version="1"
Flags="Execution, Assertion"/>
</PermissionSet>
You then add a code group that references that permission set:
Copy
<CodeGroup class="UnionCodeGroup"
version="1"
PermissionSetName="CurrencyRatesFilePermissionSet"
Name="MyNewCodeGroup"
Description="A special code group for my custom assembly.">
<IMembershipCondition class="UrlMembershipCondition"
version="1"
Url="C:\Program Files\Microsoft SQL
Server\MSRS10_50.MSSQLSERVER\MSSQL\Reporting
Services\ReportServer\bin\CurrencyConversion.dll"/>
</CodeGroup>
In order for your code to acquire the appropriate permission, you must assert the
permission within your custom assembly code. For example, if you want to add read-
only access to an XML file, C:\CurrencyRates.xml, you must add the following code to
your method:
Copy
// C#
FileIOPermission permission = new
FileIOPermission(FileIOPermissionAccess.Read, @"C:\CurrencyRates.xml");
try
{
permission.Assert();
// Load the XML currency rates file
XmlDocument doc = new XmlDocument();
doc.Load(@"C:\CurrencyRates.xml");
...
[FileIOPermissionAttribute(SecurityAction.Assert,
Read=@"C:\CurrencyRates.xml")]
For more information, see ".NET Framework Security" in the .NET Framework
Developer's Guide.
Accessing Custom Assemblies Through
Expressions
03/04/2017
2 minutes to read
Contributors
o
o all
Once you have created a custom assembly, made it available to Report Designer or the
report server, added the appropriate security policy, and added a reference to your
custom assembly in your report definition, you can access the members of the classes in
your assembly using report expressions. To refer to custom code in an expression, you
must call the member of a class within the assembly. How you do this depends on
whether the method is static or instance-based.
Calling Static Members from a Report Definition File
Static members belong to the class or type itself and not to an instantiated object. These
members can be accessed by directly calling them from the class. You should use static
members to call custom functions in a report whenever possible, because static
members perform best. To call a static member, you need to reference it as an
expression that takes the form =Namespace.Class.Method.
To call static members
To call a static member, set your expression equal to the fully qualified name of the
member, which includes the namespace, class name, and member name. The
following example calls the ToGBP method, which converts
the StandardCost field value from dollars to pounds sterling and displays it in a
report:
Copy
=CurrencyConversion.DollarCurrencyConversion.ToGBP(Fields!StandardCost.Va
lue)
Important Information Regarding Static Fields and Properties
Currently, all reports are executed in the same application domain. This means that
reports with user-specific, static data expose this data to other instances of the same
report. This condition might make it possible for the static data of one user to be
available to all users currently running a particular report. For this reason, it is highly
recommended that you not use static fields or properties in custom assemblies or in
the Code element; instead, use instance fields or properties in your reports. Static
methods can still be used, because they do not store state or data.
Calling Instance Members from a Report Definition File
If your custom assembly contains instance members that you need to access in a report
definition, you must add an instance name for your class to the report. You can add an
instance name for a class using the Code tab of the Report Properties dialog. For more
information about adding instances of classes to a report, see Custom Code and
Assembly References in Expressions in Report Designer (SSRS).
To call a static member, you need to reference it as an expression that takes the form
=Code.InstanceName.Method.
To call instance members
Copy
=Code.m_myDollarCoversion.ToEUR(Fields!StandardCost.Value)
Initializing Custom Assembly Objects
03/03/2017
2 minutes to read
Contributors
o
o all
In some cases, you may need to initialize property and field values in your custom
assembly classes when you instantiate them. You will most likely need to initialize your
custom classes with values available to you from the report's global object collections.
You do this by overriding the OnInitmethod of the Code object of a report. To
access OnInit, use the Code element of the report definition. There are two techniques
for initializing property or field values of the classes in a custom assembly that you plan
to use in your report: You can either declare and create a new instance of your class
using OnInit, or you can call a publicly available method using OnInit.
Global Object Collections and Initialization
Several collections are available to you for initializing your custom class variables. You
can use the Globals and User collections.
The Parameters, Fields and ReportItems collections are not available to you at the
point in the report lifecycle when the OnInit method is invoked. To use the shared
collections, Globals or User, you need to include the Report object reference. For
example, to initialize your custom class based on the current language of the user
accessing the report, your Code element might look like the following:
Copy
<Code>
Dim m_myClass As MyClass
One way to initialize the property and field values of a class as shown previously is to
declare your class and create a new instance of it by calling an overridden constructor.
Another way to initialize the property and field values of the classes in your custom
assemblies is to call a publicly available method that you define from
the OnInit method. You first need to add an instance name for your class in the report
definition file. Once you have added the appropriate assembly reference and instance
name, you can call your initialization method to initialize property and field values for
your class. Your OnInit method might look like the following:
Copy
<Code>
Protected Overrides Sub OnInit()
m_myClass.MyInitializationMethod(Report.User!Language, _
Report.Globals!ExecutionTime)
End Sub
</Code>
For more information about adding an assembly reference and instance name for your
custom class, see Add an Assembly Reference to a Report (SSRS).
For more information about the global object collections, see Built-in Collections in
Expressions (Report Builder and SSRS).
How to: Debug Custom Assemblies
03/14/2017
2 minutes to read
Contributors
o
o
all
The Microsoft .NET Framework provides several debugging tools that can help you
analyze your custom assembly code and locate errors in it. The best tool to use will
depend on what you are trying to accomplish. This example uses Visual Studio 2008.
The recommended way to design, develop, and test custom assemblies for Reporting
Services is to create a solution that contains both your test reports and your custom
assembly.
To debug assemblies using a single instance of Visual Studio
2. Add a new Class Library project to the existing solution. Make sure that the report
project is set as the startup project. For more information about how to accomplish
this, see your Visual Studio documentation.
3. In Solution Explorer, select the solution.
4. On the View menu, click Property Pages.
5. In the left pane, expand Common Properties if necessary, and click Project
Dependencies. Select the report project from the Project drop-down list. Select
your assembly project in the Depends On list.
6. Click OK to save the changes, and close the Property Pages dialog.
7. In Solution Explorer, select your custom assembly project.
8. On the View menu, click Property Pages.
9. Click the Build tab if you're in a C# project or the Compile tab if you're in a Visual
Basic project.
10. On the Build/Compile page, enter the path to the Report Designer folder. By
default, this is C:\Program Files\Microsoft SQL
Server\100\Tools\Binn\VSShell\Common7\IDE) in the Output Path text box. This
builds and deploys an updated version of your custom assembly directly to Report
Designer before your report is executed.
11. Once you have designed your report and developed your custom assembly, set
breakpoints in your custom assembly code.
12. Run the report under DebugLocal mode by pressing the F5 key. When the report
executes in the pop-up preview window, the debugger hits any breakpoints that
correspond to executable code in your assembly. Use F11 to step through your
custom assembly code.
To debug assemblies using two instances of Visual Studio
6. From the list of processes, select the devenv.exe process that corresponds to your
Report Project and click Attach.
7. Define the expressions that you will use in your report from your custom assembly
and design your report.
8. When you are finished designing your report, click the Preview tab.
The report executes, and the custom assembly code should break at your
predefined break points.
Note
Using the Preview tab does not enforce code permissions for the assembly. For a
complete test, which includes any code access security errors, start the report
project under the DebugLocal configuration setting.
9. Step through your code using the F11 key. For more information about debugging
using Visual Studio, see the Visual Studio documentation.