Before we explain how to add a new parameter to an SSRS report, let just remind ourselves first that there are two types of report data sets and therefore two types of SSRS reports in Dynamics 365 for Finance and Operations:
- Query based reports
- DP (Data Provider) based reports
The procedure of adding new parameters depends on this report type.
How to add a new parameter to a DP based SSRS report
A DP based SSRS report points to a DP class as its data source. A DP class fills temporary tables (actually InMemory, TempDB or Regular) using some business logic and exposes them (using SRSReportDataSetAttributes ) to the related SSRS report as data sets. Also, a DP class points to a Data contract class, which defines and stores values of this SSRS report’s parameters. And finally, a DP class can point to an AOT query which acts as Dynamic parameter. For example:
If we want to add a new parameter to a DP based report, we need to do this by adding it to the Data contract class. This was a simple procedure in AX 2012 but in Dynamics 365 for Finance and Operations, we must not use overlayering but only extensions. Unfortunately, we cannot simply extend Data contract class since extensions don’t support the attributes making the link to the data contract and dynamic parameter query. So, we have to do it the hard way.
First, we need to create a new contract (to derive from the existing one) with a new parameter, and consequently to create a new DP (to derive from the existing one) that is related to the new contract through the SRSReportParameterAttribute attribute, and then to override the processReport() method in order to use that new parameter. Consequently, we need to duplicate the existing SSRS report and select the new DP class as its data source, and afterwards to extend the existing report menu item to point to the duplicated report. Sometimes, we will need to extend the controller class too and/or implement a Print management event handler; this depends on the report to which we are adding a new parameter.
On how to duplicate a report, extend its menu item and controller class you can learn in more detail in the next chapter.
How to add a new parameter to a Query based SSRS report
A Query based SSRS report points to a query from AOT. A query defines one or more data sets while query ranges becomes report parameters within or outside Dynamic parameter.
So, let’s say that we want to add an additional report parameter Use print management destination outside Dynamic query which will not be a query range, but we will use it in the report controller class to change the current execution flow. Namely, depending on this parameter’s value, either the print destination settings selected on the report dialog form or those from Print management setup will be used when the report is executed. After this parameter is added, it will appear on the report dialog form within the Parameters tab and not within the Records to include tab:
Navigation path to this report is: Warehouse management > Inquiries & reports > Container contents report.
Step 1: Duplicating the report
Since Container contents report is a Query based SSRS report it doesn’t have a Data contract class to add a parameter. And since we don’t want to use a query range to define the Use print management destination parameter, we will add it as a separate parameter directly to the Parameters node on the report as shown on the screenshot in Step 2.
However, because we cannot use overlayering, we need to duplicate this report first and then to add the new parameter to it. We can duplicate a report by selecting it in Application Explorer and adding it to our Visual Studio project as shown below.
Step 2: Adding the parameter
We will now open our duplicated SSRS report in Solution Explorer. Expand and right-click on the Parameters node, choose New on the pop-up menu and then select Parameter. This will add a new parameter.
Use Properties to name the parameter as UsePrintManagementDestination and set its Data Type to Boolean, its Default Value to False and its Prompt String to @SYS93922 ('Use print management destination')
After we complete Step 3 and Step 4, and run the report, the newly added parameter will appear on the report dialog form.
Step 3: Extending the controller class
Now we will create a new controller class DocWHSContainerContentsController that will extend WHSContainerContentsController class and implement its main() method in order to be able to use our custom report design. Also, in the same class we will override the runPrintMgmt() method to change the built-in behavior to always use those print settings configured in Print management setup.
Add the following code to the new class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
Class DocWHSContainerContentsController extends WHSContainerContentsController { /// <summary> /// Main method to override report name /// </summary> /// <param name = "_args">Method arguments</param> public static void main(args _args) { //Declaration & Initialization of extended class DocWHSContainerContentsController controller = new DocWHSContainerContentsController(); //Setting the custom report controller.parmReportName(ssrsReportStr(DocWHSContainerContents, Report)); controller.parmArgs(_args); controller.startOperation(); } /// <summary> /// Override this method to change the behavior to always use those /// print destination settings configured in Print management setup. /// </summary> protected void runPrintMgmt() { #define.UsePrintManagementDestination("UsePrintManagementDestination") // Get the UsePrintManagementDestination parameter value. boolean usePrintManagement = this.parmReportContract().parmRdlContract() .getParameter(#UsePrintManagementDestination) .getValueTyped(); // If the parameter value is false, then we need to get and use the print // settings from the report dialog form and not from Print Management Setup. if (!usePrintManagement) { SRSPrintDestinationSettings pds = this.parmReportContract().parmPrintSettings(); PrintMgmtReportRun printMgmtReportRunInstance = printMgmtReportRun; printMgmtReportRunInstance.parmDefaultOriginalPrintJobSettings(pds); // Force the use of the print settings selected on the report dialog. printMgmtReportRunInstance.parmForcePrintJobSettings(true); } // Call super(). super(); } } |
Step 4: Extending the report output menu item
Now we will create an extension for the report output menu item (WHSContainerContents) in order to enable use of our custom controller class.
Step 5: Adding support for Print management setup
Since ContainerContentsReport report is a Print management report, we have to implement a delegate handler method that will enable our custom report design to be used with Print management setup.
We need to subscribe to the getDefaultReportFormatDelegate() delegate placed in the PrintMgtDocTypeHandlerExt class and implement its handler method in the following way.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class DocWHSContainerContentsPrintMgtDocTypeHandler { /// <summary> /// Add a subscriber method to set our custom SSRS design as a default SSRS report format /// for the WHSContainerContents PrintMgmtDocType but also to add it to Print management setup. /// </summary> /// <param name = "_docType">Print management document type</param> /// <param name = "_result">Event handler result</param> [SubscribesTo(classstr(PrintMgmtDocType), delegatestr(PrintMgmtDocType, getDefaultReportFormatDelegate))] public static void getDefaultReportFormatDelegate(PrintMgmtDocumentType _docType, EventHandlerResult _result) { // For WHSContainerContents set our custom report design as the default report design. switch (_docType) { case PrintMgmtDocumentType::WHSContainerContents: // Our custom SSRS Design _result.result(ssrsReportStr(DocWHSContainerContents, Report)); break; } } } |
After adding the delegate handler build your code and go to Print management setup (Warehouse management > Setup > Warehouse management parameters > Print management tab). You will be able to select our custom report design in the Report format combobox.
Result: Using the newly added report parameter
As you can see above, if we turn off the new parameter Use print management destination and select File as the target print destination on the report dialog form, the report will be printed to File and not to the print destination configured in Print management setup.
Hi, Thanks for this blog. Explains a lot.
1 query that I have is can we use both AOT query and dynamic query in a Ssrs report so that both types of parameters appear in the parameter box.
If so, how? I’m unable to achieve this on my own.
Thanks in advance.
Dynamic query parameter that contains query ranges from the AOT query, which acts as the report dataset, will appear in the Records to include fast tab on the report dialog form, but only if you set the Dynamic filters property of the corresponding dataset to True before picking up the source query (for setting up the Query property of the dataset).
On the other hand, if you set Dynamic filters to False, and then select (once again) your AOT query as Query of the dataset, the query ranges will be added directly to Parameters of the SSRS report. This means that they will also show up in the Parameters fast tab on the report dialog form when the report is printed. I didn’t test this myself but this is how it should work 😊
Kind regards,
Ana
Design – NewDesign, Copy all objects in OldDesign and paste in NewDesign, Delete OldDesign and Publish. This is my solution too, it works fine.
Hi, I’m getting object reference error while clicking on the “Select” button after creating a copy of the Original. It seems it’s not getting my report query.
“Original” is working fine and I’m getting the correct output of the report, this error is coming when I’m clicking on “Select” button after right click on “original” and create new. This is a custom report, standard reports are working fine.
The thing is, we want to use the option to switch on automatic printing of Container Contents report when we execute “Close container”. This toggle is on the Container Packing policy connected to one of our Packing profiles. When using this functionality, there is no “middle screen” where we can control if it is sent directly to printer or generated first to screen. Therefore, it goes straight to screen without any option to do otherwise. We have tried making setup in Document Management for it, but it does not help. Is coding the only way to make this document go directly to printer? And how come this bug is not fixed still after 4 years?
Hi Helena,
When you run the “Close container” which report is running? I don’t have data in my environment to run and verify the process. I looked at the code that is called once the “Close container” button is clicked and couldn’t find any piece of code that calls the Container Contents report. If you can run this in dev environment, then I suggest debugging and checking how the flow is. A few years ago, we found that the Container contents report is always printed to Screen, here is the link to article That issue was solved by MS in later versions, as I can see.
Best regards,
Jovica.