Many applications, both Windows and Web, need to connect to the Internet to send or receive data. ASNA Visual RPG Classic apps do not intrinsically have the ability to make HTTP requests. This can be a crippling drawback when you have a legacy enterprise app for which you now have the requirement to send and/or receive data from the Internet. There are still a few third-party COM controls around that can enable AVR to make HTTP requests, but these controls are often troublesome and customers report that some no longer work.

This article shows how to extend AVR Classic with AVR for .NET to enable the AVR Classic app to fetch the Json data with an HTTP request. We’ll first a look at the AVR for .NET class library project responsible for making the HTTP request to fetch the Json then we’ll take a look at the AVR Classic app that consumes that .NET class library. This article provides a simple example of fetching Json. Things like user authentication and product-worthy error handling are omitted–but both can be added.

This article is the third in a series about integrating AVR for .NET with AVR Classic. The other two are:

Other articles that may be helpful are:

Let’s start with a preview of the results. The image below shows an AVR Classic app with a simple subfile. This subfile has been populated with Json data read from the Internet–with a little help from AVR for .NET. You may not need to populate a subfile with Json data, but the subfile is a good way to show results.

The Json data

First, we need some Json test data. The JSONPlaceholder site provides several different Json test documents. This article uses its users Json document. This URL provides fictitious Json data for 10 users and a fragment of it is shown below in Figure 1.

Figure 1. Sample Json data from https://jsonplaceholder.typicode.com/users

The red box in Figure 1 above outlines a single user element in the Json document. Each user in this Json document has nested data in its addressgeo, and company values. We’ll need a set of AVR for .NET classes to model this data so we can deserialize the Json data into a data format easily accessible by the AVR Classic app.

The AVR for .NET class library

To integrate AVR for .NET with AVR Classic, we’ll start by building an AVR for .NET class library. This library will offer AVR Classic what it sees as a custom COM component with the ability to make an HTTP request.

The AVR for .NET classes that model this data are shown below in Figure 2a. It’s generally a best practice to put each class in its own source file, but to minimize the chunks presented here I’m cheating and putting these four classes in a single source member.

Figure 2a. Sample Json data from https://jsonplaceholder.typicode.com/users.

Figure 2a is a single source member that provides four classes:

Notice how the structure of these four classes echoes exactly the nested structure presented by the Json test data. Ultimately, we’ll be able to fetch a user property with a nested object syntax like this:

It’s very important that the structures created to represent the Json data do so accurately. Take your time and declare your data description classes very carefully. The ability to deserialize the incoming Json into a .NET object depends on their schema correctly echoing the Json schema.

You’ll notice that the .NET attributes ComVisible and ClassInterface have been applied to all four of the data description classes in Figure 2a. These attributes are necessary to surface .NET classes (and their properties and members) to COM. This asna.com article goes into more detail about these attributes. These attributes are applied to all four of the classes in Figure 2a.

Assigning the ComVisible and ClassInterface attributes used to expose .NET classes to COM don’t affect the ability of those classes to also be consumed by .NET. These classes can still be used in .NET-only projects. There may be some performance penalty imposed so watch for that–but that doesn’t appear to a significant issue.

The second AVR for .NET class needed is one to make the HTTP request to fetch the Json. That Request class is shown below in Figure 2b.

Figure 2b. The AVR for .NET Request class.

The Request class has two properties:

The Request class has two methods:

Note that nothing in the Request class is surfaced directly to COM.

The third and final AVR for .NET class required for this example is a class to surface Figure 2b’s GetJson method and some other necessary properties. My contention is to call this class ComBridge and it is shown in Figure 2c below.

Debugging between AVR Classic and AVR for .NET is challenging. You can’t interactively debug from one environment to the other. The ComBridge class makes it easy to package and test exactly what the COM app needs–and this minimizes the .NET debugging required. As you build .NET components for AVR Classic consumption code defensively and test your .NET components carefully before attempting to consume them with COM. A .NET test harness to test your .NET work first is a good way to avoid debugging pain later.

Figure 2c. The ComBridge class which surfaces .NET functionality to AVR Classic.

Like the data classes in Figure 2a, the ComBridge class is also decorated with the ComVisible and ClassInterface attributes.

ComBridge has three properties:

Limit the data types you surface to COM from .NET to scalar types (strings and numbers, essentially) and data classes (like the four we’re using from Figure 2a). Even simple .NET objects like date data types can cause issues with COM. Use getter functions (like this example does) and keep the interface between the two environments simple.

ComBridge surfaces two methods to AVR Classic:

After compiling the .NET project, .NET’s RegAsmutility must be used to create COM-based type library needed for AVR Classic. RegAsm and how to use it is explained in this article. After running RegAsm you’ll see that library in the same folder as the .NET DLL–the only difference is the COM library has a .tlb extension. RegAsm created the library and registered with COM on your system.

The AVR classic app to consume the .NET class library

Consuming the AVR for .NET project’s DLL with AVR Classic is pretty simple. With a new project started, we first need to set a reference to the COM class library that the AVR for.NET project created. In this example, that DLL is named AVRClassicHelper_Http. The .NET project name was AVR ClassicHelper.HTTP and when RegAsm compiles the COM type library, it swaps out the period for an underscore. Figure 3a below shows AVR Classic’s References window with this reference set.

Figure 3a. AVR Classic’s References window

Having set that reference, we can use AVR Classic’s Object Browser to see what that reference makes available to AVR Classic, as shown below in Figure 3b.

Figure 3b. AVR Classic’s Object Browser window

AVR Classic’s Object Browser shows what .NET components the reference made available: the four data classes (UserAddressInfoCompanyInfo, and GeoInfo) and the ComBridge class. The Object Browser view in Figure 3b shows methods and properties that the ComBridge makes available. You’ll use AVR Classic’s Object Browser frequently to ensure the members and properties you think should be there are actually there and to see how to declare the classes (in the bottom of the Object Browser window).

You also notice that the ComBridge class surfaces members (the properties EqualsGetTypeGetHashCodeGetType, and the method ToString) that weren’t explicitly defined in the ComBridge class in the .NET project. These members are aritifacts of .NET object inheritance and you can generally ignore them.

The AVR Classic code to use the ComBridge class is shown below in Figure 4a:

Figure 4a. The AVR Classic code to consume the .NET components.

This line from the code above calls the .NET CallGet() method, passing it a URL:

If the call is successful, UserCount indicates the number of Json elements available and httpGetJson.HttpStatus will be 200. If the call isn’t successful UserCount is -1 and the httpGetJson.HttpStatus code is the HTTP status code received from the HTTP request. If an error occurred, the error message is in the httpGetJson.ErrorMessage property.

Because AVR Classic can’t access the .NET array of users directly, it uses a loop and the .NET httpGetJson.GetUser function to fetch each user. When a user is fetched WriteSubFile is called to add that user to the subfile.

The results of the code in Figure 4a are shown below in Figure 4b:

Figure 4b. The AVR Classic app showing Json data in a subfile.

Summary

Integrating AVR Classic with AVR for .NET is an intermediate/advanced topic to be sure. However, once you master the basics, it’s actually pretty easy to do, and the power and possibilities that .NET can provide to COM are nearly endless.

Considerations:


Sidebar: A quick note on fetching the Json response

The AVR for .NET GetRequest method in Figure 2b above has about 45 lines of code, however much of that code is error handling. The core facility to issue an HTTP request and convert its response to a string is shown below in Figure A.

Figure A. Traditional AVR for .NET code to work with HTTP.

The code above uses the .NET HttpWebRequest and HttpWebResponses classes from the System.Net namespace to issue an HTTP GET request and process its response.

We’ve been doing HTTP work with AVR for .NET for a long time and have always used the HttpWebRequest/HttpWebResponse APIs. The grungy part of using HttpWebRequest/HttpWebResponse isn’t issuing the HTTP request, it’s the four mysterious lines of code required to convert the response into a string. It occurred to me during this .NET->COM project that maybe there are better ways to work with HTTP in .NET now.

This article lead me to the RestSharp open source project. With nearly 17m downloads on nuget.org RestSharp must have something going for it. I gave it a quick spin with AVR for .NET and was impressed with its concise API and direct way of doing things. With RestSharp the code in Figure A above is reduced to the code in Figure B below:

Figure B. The RestSharp equivalent of Figure A.

The RestSharp API is comprehensive and has features for authentication and serialization baked in. It looks like a promising API for .NET HTTP work.