.net equivalent to MSXML2.XMLHTTP for sending https POST req

Posted by Ken Ward on 06-Apr-2017 13:02

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.

Posted by tbergman on 06-Apr-2017 20:50

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.

All Replies

Posted by tbergman on 06-Apr-2017 14:41

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.

Posted by Ken Ward on 06-Apr-2017 14:52

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?

Posted by tbergman on 06-Apr-2017 20:50

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.

Posted by Ken Ward on 07-Apr-2017 09:45

My system is not recognizing the HttpClient Class. Even when I put the whole namespace in front of it. Am I missing an assembly?

Posted by jquerijero on 07-Apr-2017 10:33

Try adding this to your assemblies.xml.

<assembly name="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>

Posted by Ken Ward on 07-Apr-2017 11:08

I've added this line and restarted the Appbuilder (yes I'm using the app builder here). It still doesn't recognize the namespace.

Posted by tbergman on 07-Apr-2017 11:11

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.

Posted by jquerijero on 07-Apr-2017 11:14

Try adding reference to System.Net.Http.dll.

Posted by asaynes on 07-Apr-2017 12:13

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."

Posted by Ken Ward on 07-Apr-2017 12:46

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.


Posted by tbergman on 07-Apr-2017 15:06

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.

Posted by Ken Ward on 10-Apr-2017 09:04

sorry, I have tried it with version 4.0.0.0 in the assemblies.xml file. I still get the same result.

Posted by Ken Ward on 10-Apr-2017 09:45

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?

Posted by tbergman on 11-Apr-2017 21:30

You’ll need a reference in your assemblies file to System.Net.Http.
 
Tom
 

Posted by jquerijero on 26-Apr-2017 13:28

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.

This thread is closed