Getting Started With IBM i, .Net, and XMLSERVICE Remote Commands
August 30, 2016 Richard Schoen
Running CL commands and submitting batch jobs are great ways to use existing program functionality from a .Net desktop, web, or web service application. In this article we’ll focus on the XMLSERVICE remote command functionality. You’ll see just how easy it is to use XMLSERVICE to run programs or submit batch jobs on your IBM i systems.
In this installment we’ll begin to tour the XMLSERVICEi .Net application code and samples, starting with the remote command call example. If you haven’t installed and set up the XMLSERVICE application code and created an Apache web server instance yet, please check out the introductory article before continuing, since XMLSERVICE must be up and running before our .Net application code will work. I also assume that you’ve opened, configured and run the test application at least once.
Before I continue, let me mention an important event that recently occurred. In July, the new multi-platform Microsoft .Net Core 1.0 version was released, making it more timely to have an XMLSERVICE wrapper available for .Net. Since the IBM i Access ODBC drivers won’t work with .Net Core on non-Windows platforms such as Linux and MacOS, XMLSERVICE will play an even more important data access role if you’re developing new .Net or .Net Core applications for IBM i. See www.microsoft.com/net/core#windows for more information.
Running the Test App
Go ahead and launch Visual Studio, then load and open the XmlServiceApi solution file C:XmlServiceiApiXmlServiceiApi.sln. Locate the XmlServiceApiTester project within the solution and double-click FormMain.vb to open the main form.
If you have configured things correctly, you should be able to press the play button to make the API tester application run and display its application window. To test the CL command functionality in the API, type a test CL command, such as SNDMSG MSG(TEST) TOUSR(QSYSOPR), and click the Run CL Command button to run the selected CL command. If you prefer, use the default command that was already entered. After the CL command runs, message response information will be displayed in the XML results Window and within the data grid. A return code of true is also returned from the ExecuteCommand function if it succeeds. If the command fails, a return code of false is returned. If a value of true is returned, you can assume your remote command call was successful.
Reviewing The Code
Let’s take a quick look at the code that runs the remote command. First you must set up connectivity parameters. To set up for any call to the IBM i, use the SetBaseURL function to set the base URL into the XMLSERVICE object from the test project settings. Next, use the SetUserInfo function to set the desired IBM i user and password from the settings. In a real application you might ask the user to enter a user ID and password value. Call the SetIpcInfo function to set the unique IPC conversation for this connection. This function connects the .Net application to the associated IBM i job that allows job persistence. Use the SetHttpTimeout function to determine how many seconds the HTTP connection will run before it times out. I normally use 30 seconds for a transaction timeout. You can set it higher or lower depending on your expected transaction length.
After the setup work is done, pass the appropriate CL command line to the ExecuteCommand function, which either completes successfully and returns a value of true, or fails and returns a value of false. It’s important to note that when you call CL commands from a remote application, you will need to make sure to handle any errors within the called RPG, CL or COBOL code behind the CL command. If you don’t handle errors, your IBM i program may throw a CPF exception error message to QSYSOPR. To the end user this can appear as if their .Net application has locked up, when in fact it’s waiting for a response from the system operator. The HTTP server will timeout eventually, but it’s not nice for your XMLSERVICE apps to throw a hard halt. Code diligently and anticipate errors. Properly handling remote program call errors is not unique to .Net. The same problem can occur when using other languages, such as PHP, Java, and Ruby, to call commands remotely.
Let’s look at the VB code behind the Run CL Command button click to see how easy it is to use the XMLSERVICEi data access object to call CL commands. Double-click on the open FormMain designer window or right-click on FormMain.vb and select View Code to open the code window. When you look at the code behind for FormMain.vb, you will see that we import the XMLServiceiApi namespace (Imports XMLServiceiApi) so that we don’t have to prefix all of our code calls with XMLServiceiApi. That would get tedious. Then, since this is a desktop application, we create a variable called _xmlService (Dim _xmlService As New XmlServicei), which gets initialized at program startup with our connection information. Using this variable lets us re-use the same connection while the Windows application is active. For web applications this info would possibly get stored in the web session or instantiated for each page call, since XMLSERVICE connections are stateless.
To access the Run CL Command code, double-click on the Run CL Command button. This opens the ButtonCLCommand_Click subroutine. You will notice that I like to wrap all of my code calls with Try/Catch to handle errors. This is similar to the MONMSG CL command and the MONITOR and END-MON op codes in RPG. You will also notice that SetBaseURL, SetUserInfo, SetIpcInfo, and SetHttpTimeout are all called to set up the connection and login info from the app configuration. Normally you would prompt the user to enter those settings. Then you see the single call to the ExecuteCommand function to run the CL command.
After the CL command call completes, the GetDataTableCommandResponse function is called to bring back the responses in DataTable format, which displays them in a grid. We call GetLastXmlResponse to display or process the entire XML response string from XMLSERVICE if desired. When you use the XmlServiceiApi wrapper, it’s this simple to call CL commands from a.Net application. If you’re feeling super adventurous, you can open up XmlServicei.vb source and take a look at the ExecuteCommand code. You will see that the function composes an XML data stream to post to the XMLSERVICE xmlcgi program via HTTP and processes the XML responses. There’s very little .Net communications plumbing code required since XMLSERVICE does most of the heavy lifting work on the IBM i side and we just call it via HTTP or HTTPS for secure calls.
To The Next Step
Since the IBM i Access ODBC drivers won’t work with .Net Core on other platforms, such as Linux and OS X, it is even more important for you to use XMLSERVICE when you’re developing new .Net or .Net Core applications for IBM i.
In the next article, we will review the program call and stored procedure call functionality. Let me end with a quick commentary on providing feedback to me on the XmlServiceiApi project.
I’m not sure about most open source projects but I have received very little feedback on this project since it was released in early 2015. However, at least one person has forked the code and converted it to C# without any feedback to me. If you have any contributions to make to the XmlServiceiApi project, I would appreciate if you would please pass them directly to me so I can incorporate them into the project rather than finding them on a Google search. Rather than having several project forks, it would be nice to have one main development line. However, in the spirit of open source, you can do what you want with the code. Until next time.
Richard Schoen is Director of Document Management for HelpSystems where he spends his time helping customers learn about automating document based processes and implementing automated business processes and system integrations using all of the HelpSystems products. You can contact Richard via email email with questions, comments or article ideas. You can also find Richard on Twitter (@richardschoen) or LinkedIn.