I'm using OpenEdge 11.2, and I'm looking for a way to do https requests that doesn't use the MSXML2.XMLHTTP ActiveX object.
Sample Text:
DEF VAR client AS COM-HANDLE NO-UNDO.
DEF VAR vBody AS CHARACTER NO-UNDO.
vBody = "ParmList=UN~~*******|PSWD~~************|" +
"TERMS~~Y|METHOD~~ProcessTranx|TRANXTYPE~~Sale|" +
"AMOUNT~~5.00|CC~~****************|" +
"EXPMNTH~~03|EXPYR~~2022|". CREATE "MSXML2.XMLHTTP" client. client:OPEN("POST", "paytrace.com/.../default.pay", FALSE). client:SetRequestHeader("Content-Type", "application/x-www-form-urlencoded"). client:Send(vBody). MESSAGE client:ResponseText VIEW-AS ALERT-BOX. RELEASE OBJECT client.
Whenever I run this code, I get the error:
Error occurred while accessing component property/method: Send.
The system cannot locate the resource specified.
Error Code: 0x80020009 D:\dvl\tmp\p50651_cc_QuickTest.cmp (5890)
If I send the same request using a program like Postman or sites like hurl.it, it works fine.
To make it worse, certain other programs in our system use code just like this and they work fine as well.
For adding headers and setting content-type it's best to use the httpRequestMessage when using HttpClient.
The code below shows another usage where headers anhd content type are set. Content-type is not an ordinary header like SOAPAction below. It needs to be done as a part of setting the content.
The Uri should be just what you'd type in a browser, no href.
httpClient = NEW System.Net.Http.HttpClient(). httpRequestMessage = NEW System.Net.Http.HttpRequestMessage(). httpRequestMessage:Method = System.Net.Http.HttpMethod:Post. httpRequestMessage:RequestUri = NEW System.Uri(vUrl). httpRequestMessage:Content = NEW System.Net.Http.StringContent(xmlRequest, System.Text.Encoding:UTF8, "text/xml"). httpRequestMessage:Headers:Add ("SOAPAction","~"~""). /* Use SendAsync in a synchronous manner by directly accessing the result */ httpResponseMessage = httpClient:SendAsync(httpRequestMessage):Result. xmlResponse = httpResponseMessage:Content:ReadAsStringAsync():RESULT NO-ERROR.
Here's some code I recently wrote to talk to Google for CAPTCHA verification. It posts using the .Net HttpClient.
Hopefully this will be enough to get you started.
USING System.Net.Http.*. USING System.Collections.Generic.*. USING Progress.Lang.*. USING Progress.Json.ObjectModel.*. METHOD PUBLIC LOGICAL VerifyCaptcha( INPUT CaptchaResponse AS CHARACTER, INPUT IPAddress AS CHARACTER ): DEFINE VARIABLE Client AS HttpClient. DEFINE VARIABLE Response AS HttpResponseMessage. DEFINE VARIABLE JsonParser AS ObjectModelParser. DEFINE VARIABLE ValuesCollection AS "Dictionary<Char,Char>". JsonParser = NEW ObjectModelParser(). Client = NEW HttpClient(). Client:BaseAddress = NEW System.Uri("www.google.com/.../siteverify"). ValuesCollection = NEW "Dictionary<Char,Char>"(). ValuesCollection:Add("secret","xxxxxxx"). ValuesCollection:Add("response",CaptchaResponse). ValuesCollection:Add("remoteip",IPAddress). Response = Client:PostAsync( "", NEW FormUrlEncodedContent(ValuesCollection)) :Result. CaptchaResponse = Response:Content:ReadAsStringAsync():RESULT. IF CAST(JsonParser:Parse(CaptchaResponse),JsonObject):GetLogical("success") THEN RETURN TRUE. ELSE RETURN FALSE. END METHOD.
I look forward to trying this, but I have a couple questions:
Does the System.Uri() need to be in the form of an <a> tag or can it just be a URL?
Is there a way to set headers like Content-Type?
For adding headers and setting content-type it's best to use the httpRequestMessage when using HttpClient.
The code below shows another usage where headers anhd content type are set. Content-type is not an ordinary header like SOAPAction below. It needs to be done as a part of setting the content.
The Uri should be just what you'd type in a browser, no href.
httpClient = NEW System.Net.Http.HttpClient(). httpRequestMessage = NEW System.Net.Http.HttpRequestMessage(). httpRequestMessage:Method = System.Net.Http.HttpMethod:Post. httpRequestMessage:RequestUri = NEW System.Uri(vUrl). httpRequestMessage:Content = NEW System.Net.Http.StringContent(xmlRequest, System.Text.Encoding:UTF8, "text/xml"). httpRequestMessage:Headers:Add ("SOAPAction","~"~""). /* Use SendAsync in a synchronous manner by directly accessing the result */ httpResponseMessage = httpClient:SendAsync(httpRequestMessage):Result. xmlResponse = httpResponseMessage:Content:ReadAsStringAsync():RESULT NO-ERROR.
My system is not recognizing the HttpClient Class. Even when I put the whole namespace in front of it. Am I missing an assembly?
Try adding this to your assemblies.xml.
<assembly name="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
I've added this line and restarted the Appbuilder (yes I'm using the app builder here). It still doesn't recognize the namespace.
Try
<assembly name="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
I'm not sure it existed in the earlier versions in .Net. The above is what I have in my assemblies file. BTW, I always use the "Add Assembly References" choice in PDS rather than editing the xml by hand.
Try adding reference to System.Net.Http.dll.
HttpClient is not supported in OE 11.2. It's supported from OE 11.5.1
knowledgebase.progress.com/.../Is-there-an-HTTP-client-for-OpenEdge
"Customers on OpenEdge versions between 10.2x and 11.5 could use the .NET HttpClient. However, unlike the ABL HTTP Client, this code can only be used on Windows platforms."
Ah yes, I was aware of this. Unfortunately, we are in a transition between 11.2 and 11.6, but this code is needed for our 11.2 customers.
As best as I can tell, the sample code given by tbergman IS using .net and not an ABL solution.
Our 11.2 environment doesn't have the Eclipse editor installed on it, so I don't know of any other way to add references aside from modifying the assemblies.xml file manually.
Here is what that file currently contains:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <references> <assembly name="Accessibility, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <assembly name="SigPlusNET, Version=2.0.0.42, Culture=neutral, PublicKeyToken=6aef07010bb0624f"/> <assembly name="ceTe.DynamicPDF.40, Version=8.0.1.40, Culture=neutral, PublicKeyToken=09b5ce0d5c0a9d8b"/> <assembly name="ceTe.DynamicPDF.Viewer.40.x86, Version=1.0.3.30310, Culture=neutral, PublicKeyToken=09b5ce0d5c0a9d8b"/> <assembly name="ceTe.DynamicPDF.Printing.40.x86, Version=2.0.2.31045, Culture=neutral, PublicKeyToken=09b5ce0d5c0a9d8b" /> <assembly name="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> <assembly name="System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <assembly name="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> <assembly name="System.Deployment, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <assembly name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <assembly name="System.Runtime.Serialization.Formatters.Soap, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <assembly name="System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <assembly name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> <assembly name="System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> <assembly name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> <assembly name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <assembly name="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> <assembly name="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <assembly name="System.Net, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <assembly name="TECIT.TBarCode, Version=11.0.0.0, Culture=neutral, PublicKeyToken=1b5f4306b234b83d"/> </references>
and here is my current sample code based on the prior suggested answer:
USING System.Net.Http.*. USING Progress.Lang.*. DEF VAR httpClient AS CLASS "System.Net.Http.HttpClient" NO-UNDO. DEF VAR httpRequestMessage AS CLASS "System.Net.Http.HttpRequestMessage" NO-UNDO. DEF VAR httpResponseMessage AS CLASS "System.Net.Http.HttpResponseMessage" NO-UNDO. DEF VAR vRequest AS CHAR NO-UNDO. DEF VAR vResponse AS CHAR NO-UNDO. vRequest = "ParmList=" + "UN~~*******|PSWD~~************|" + "TERMS~~Y|METHOD~~ProcessTranx|TRANXTYPE~~Sale|" + "AMOUNT~~5.00|CC~~****************|" + "EXPMNTH~~03|EXPYR~~2022|TEST~~Y|". httpClient = NEW System.Net.Http.HttpClient(). httpRequestMessage = NEW System.Net.Http.HttpRequestMessage(). httpRequestMessage:Method = System.Net.Http.HttpMethod:Post. httpRequestMessage:RequestUri = NEW System.Uri("https://paytrace.com/api/default.pay"). httpRequestMessage:Content = NEW System.Net.Http.StringContent(vRequest, System.Text.Encoding:UTF8, "application/x-www-form-urlencoded"). httpResponseMessage = httpClient:SendAsync(httpRequestMessage):Result. vResponse = httpResponseMessage:Content:ReadAsStringAsync():RESULT NO-ERROR.
As mentioned above, you will need to add a line to your assemblies file.
Mine contains
<assembly name="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
The code I provided will not work without this line.
sorry, I have tried it with version 4.0.0.0 in the assemblies.xml file. I still get the same result.
I was looking at some sample code for a different part of this project and this (c#) code was using the System.Web namespace.
I was not able to open its project because IIS is not installed in our environment. Is it possible that this is not working for me because I don't have IIS installed?
If you decide to use System.Web namespace, you will need to add;
<assembly name="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
And most importantly, you will need to install .NET Framework 2.