C# to OpenEdge

Posted by bbrennan on 19-Apr-2016 18:32

I have a set of C# samples for a REST based web services project.  I am looking at converting some of these samples from C# to ABL as a proof of concept.  Are there resources available that document any of the differences between the languages?  A quick set of searches is not encouraging.

Thanks for any pointers or advice.

Bob Brennan

IMS, Inc.

All Replies

Posted by aestrada on 19-Apr-2016 21:58

This is an extremely minimal example but the Progress Github has some code that does a C# equivalent of an ABL DB query.

You can find it here: github.com/.../BasicQuery

There're more examples (such as a complex join on tables, ORM's vs temptables) but they're more geared towards Java and Python. Primarily because I know more Java and Python than C#.

Hope this helps!

Posted by Roger Blanchard on 20-Apr-2016 06:24

Hey Bob,

Are you looking for ABL to make a REST call or for ABL on the server to handle the REST call? I have 11.4 client code that will make a REST call. We have been using this in production for 18 months or so.

Posted by Peter Judge on 20-Apr-2016 07:48

I don't think there's a formal doc or wiki out there. I've found it fairly simple to convert C# to OOABL with a few gotchas
- event handlers (cannot use delegates IIRC)
- the using keyword and casting is slightly different
- obvs the variable definitions and init are inline in C#
- generics and generic methods in particular may cause trouble
- no threading allowed in ABL
- need to use some helper classes for enums and other .NET types
- need to use a .NET-based WAIT-FOR
 
The list is from memory and from posts to PSDN/Communities over the years.
 
You could also follow Roger's approach.
 

Posted by bbrennan on 20-Apr-2016 20:03

Thanks everyone.  We are looking to integrate an application written in ABL to a back end that offers REST based web services.  The samples we have calling these web services are based on C#.  Their model includes all of the service calls we need as methods, so we are shielded from needing to really do much in ABL.  My issue is that there are a number of things that I see in the C# code that don't seem to translate and in some cases are not supported by ABL.  An example is the use of Generics.

The back end guys have published .NET helper classes that really seem to get us about 80% of what we need in terms of getting data in useful formats.  Not being fluent in C# or .NET for that matter really make this a stuttered approach.  Find some new C# construct, learn some about it, look for an equivalent in ABL and repeat.  Does not help that I am also new to OOABL.

Posted by Roger Blanchard on 21-Apr-2016 07:32

Hey Bob,

We have our ABL client making REST calls to a 3rd party service. We also have our ABL client making REST calls to our ABL backend. Both of these implementations are sending/receiving XML. We did not have to play around with "Generics". If you want to email me I can send you a sample class that we are using to make the REST call.

Roger

Posted by bbrennan on 28-Apr-2016 11:13

I am trying to translate the following example from C# into  ABL 11.6.1

I am struggling trying to translate 

           List<Customer> items = clientHelper.GetItems<Customer>(request);

The following is a full sample of a C# demo.  The web service can deliver the results as Raw JSON, a JSON Object or a mapped list. 

I can successfully call the web service.  In the case of returning a list of customer, I am struggling with how to manage/deal with the returned values.

I am thinking I want a mapped list instead of a JSON Object but that might not be possible.  

Thanks for any feedback.  Like I have said before C#, .NET things and OOABL  are all new to me.

Bob

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

using System;

using System.Collections.Generic;

using IMS.Entities.Lib.API;

using IMS.Entities.Lib.CRM;

using IMS.WebAPIClient;

using IMS.WebAPIClient.RequestBuilder;

namespace IMS.WebAPI.Examples.Customers.Data

{

   public class CustomerRepository

   {

       private const string UrlGetCustomers = "/CRM/CustomerCentral/Customers/"; // GET

       private const string UrlUpdateCustomer = "/CRM/CustomerCentral/UpdateCustomer/"; // POST

       private const string UrlDeleteCustomer = "/CRM/CustomerCentral/DeleteCustomer/"; // POST

       public static List<Customer> GetCustomers()

       {

           IMSServiceClient clientHelper = SessionManager.Instance().GetServiceClient();

           ServiceRequest request = clientHelper.NewRequest(UrlGetCustomers);

           request.SetHttpMethod("GET");

           // Get json object

           // JObject json = clientHelper.GetJson(request);

           // Get raw json response

           // string rawResponse = clientHelper.GetRawResponse(request);

           // Get mapped Customer list

           List<Customer> items = clientHelper.GetItems<Customer>(request);

           return items;

       }

         public static void UpdateCustomer(Customer customer)

       {

           IMSServiceClient clientHelper = SessionManager.Instance().GetServiceClient();

           ServiceRequest request = clientHelper.NewRequest(UrlUpdateCustomer);

           request.SetHttpMethod("POST");

           request.SetDataObject(customer);

           IqWebResponse response = clientHelper.GetSuccessResult(request);

           if (!response.DidSucceed)

               throw new ApplicationException(string.Format("Error updating customer - {0}", response.Message));

       }

   }

}

Posted by Mike Fechner on 28-Apr-2016 11:22

The question is what is IQMSServiceClient. Is this a generic class? That needs instantiation with a <Customer> type parameter?
 
If not, then this looks like a generic method on a non generic type. ABL can only use generic methods of generic types. Unfortunately.

Posted by tbergman on 28-Apr-2016 12:48

Hi Bob,
 
While there are likely many ways to deal with this, it may be simpler to think about this in terms of “send some text via HTTP”, “get back some text via HTTP”. Then do something with what you get back. This might mean forgetting about the libraries they provided. Possibly using their libraries with what you called “Raw Json” could also be considered. I’m not at all sure what their “JsonObject” is, it’s possible you could use that as well to parse your way through the Json.
 
If there’s a way to test this service from a web browser, do that and examine the returned content. If not, try using a tool for REST (fiddler, SoapUI, probably others) and configuring the call. Or if you have a working sample from the vendor, sniff the conversation using Fiddler.
 
Once you know the text being sent and received, and possibly a few things about the headers, you just have to figure out how to do this in Progress. I use the .Net WebClient or HttpClient to do this sort of thing. Then Progress or .Net tools for parsing the JSON/XML or whatever comes back. Parsing thorugh the Json and doing something with it is really not so different from parsing some csv and doing something.  
 
My .Net presentation from last year’s PugChallenge has a few examples of using WebClient, I know you know where to find it. Progress 11.6 has its own HttpClient capabilities (platform independent) but I haven’t spent any time with it.
 
Tom
 
 
 
 
 

Posted by Peter Judge on 28-Apr-2016 13:04

There's also the ABL http client that you can use.  It's quite easy to use (the main trick is knowng how to process the Entity property which contains the response body).
 
For example:
 
using OpenEdge.Net.HTTP.IHttpRequest.
using OpenEdge.Net.HTTP.RequestBuilder.
using OpenEdge.Net.HTTP.IHttpResponse.
using OpenEdge.Net.HTTP.IHttpClient.
using OpenEdge.Net.HTTP.ClientBuilder.
using OpenEdge.Net.HTTP.Credentials.
 
def var oReq as IHttpRequest.
def var oResp as IHttpResponse.
def var oClient as IHttpClient.
 
oReq = RequestBuilder:Get('devlinux12:2412/.../get_field.p)
            :Request.
 
oReq = RequestBuilder:Get('localhost:8820/.../applications')
            :UsingBasicAuthentication(new Credentials('admin', 'tomcat', 'tomcat'))
            :Request.
 
oReq = RequestBuilder:Get('devlinux12:2409/.../workshop')
            :Request.
 
 
oClient = ClientBuilder:Build():Client.
 
oResp = oClient:Execute(oReq).
 
message
oResp:ContentType skip
oResp:ContentLength skip(2)
oResp:Entity:ToString()
view-as alert-box.
 
 
There's also API doc at https://documentation.progress.com/output/oehttpclient/ and some other examples on these fora.
 

This thread is closed