REST service does not work

This forum is meant for questions and discussions about the X# language and tools
Post Reply
ic2
Posts: 1798
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

REST service does not work

Post by ic2 »

With our converted VO program to X# we have a problem with a REST service which is supposed to send an XML file with PDF link to a web address, using a C# function as a replacement for an old Visual Objects function. The PDF file is uploaded via FTP and the XML is giving location info.

We get a response back that this is successful httpResponse.StatusCode = 200 (implying success), however no PDF is uploaded and we also get back the result message "disallowed key characters". This error suggest that the web address contains invalid characters, however, the address is not only the same as in the VO program, it completely consists of lower case letters - not even a number or other character.

Nor the XML file, or the web address has changed since the old Visual Objects function and still looks the same. In VO we use a method called:
METHOD GetDocumentByGetOrPost(cIP, cDocument, cData, cHeader, cMethod, nP, nFlags) CLASS cHttp
which is from Norbert Kolb, he wrote that in 2003. This VO code works without problems. Basically it goes through these calls:

SELF:hConnect := InternetConnect(parameters)
....
IF SELF:hConnect <> NULL_PTR
SELF:__SetStatusObject()

SELF:hRequest := HttpOpenRequest(parameters)
...
IF HttpAddRequestHeaders
...
HttpSendRequest(SELF:hRequest, ;
...
cRet := SELF:GetResponse() // -->cRet is successful.

The equivalent .Net code looks a lot more compact with far less of the above steps and that would be great - if it worked.

The XML is:

<Root>
<Documents>
<Document>
<Location>(location info of the PDF uploaded via FTP)</Location>
<ShipmentID>id</ShipmentID>
<Title>Cmr</Title>
</Document>
</Documents>
</Root>


This XML file is supposed to move a PDF to the website/program, however, it does not. The web address and password are correct (and the same as generated by the VO code).

Below is our C# function. We use X# to make the XML file, this pretty much works the same as the old Visual Objects function, since we converted this with the X# converter.

Did anybody encounter problems and find a solution which we can apply too?

The next step we can try is to revert to the original VO code of 2003, but one of the reasons to move to X# is that we want to rely on modern & compact .Net code. Problem is that most of the times, the old fashioned VO code works while the .Net alternative does not :angry:

Dick
[hr]
public bool PostXml(string cXml, string cAdres,string cSecret, string cHeader)
{
try
{
var httpWebRequest = (System.Net.HttpWebRequest)WebRequest.Create(cAdres);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Accept = "text/xml";
httpWebRequest.Method = "POST";
httpWebRequest.Credentials = new NetworkCredential(cAdres, cSecret);
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(cXml);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd(); // this returns 'disallowed characters in key'
int nStatusCode = (int)httpResponse.StatusCode; // this returns 200 which implies success

}
return true;
}
catch (Exception e)

{
return false;
}

}
steveferrandino
Posts: 33
Joined: Tue Jan 05, 2016 8:00 pm

REST service does not work

Post by steveferrandino »

Hi Dick,

I recently had a problem that was due to the REST service I was calling changing their SSL/TLS settings. I'm not sure if this is the same problem, or not but try adding this line before the webrequest.create():

ServicePointManager.SecurityProtocol := SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls

SteveF
MathiasHakansson
Posts: 50
Joined: Fri Feb 16, 2018 7:52 am

REST service does not work

Post by MathiasHakansson »

Hi,

This code is for C# and it's made for getting a token from a rest API service. It's quite similar, but some details are different from yours. It may give clues on what to experiment with...

public enum HttpVerb
{
GET,
POST,
PUT,
DELETE
}

public class RestClient
{
public string EndPoint { get; set; }
public HttpVerb Method { get; set; }
public string ContentType { get; set; }
public NameValueCollection PostData { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Accept { get; set; }

public const string ContentTypeJson = "application/json";

public string MakeRequest(string parameters = "")
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(EndPoint + parameters);
request.Method = Method.ToString();
request.ContentLength = 0;
request.ContentType = ContentType;
request.Accept = Accept;
request.Headers[HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes($"{UserName}:{Password}"));

string data = string.Empty;
foreach (string key in PostData)
data += $"{'"'}{key}{'"'}:{'"'}{PostData[key]}{'"'},";
if (data.Length > 1)
data = data.Substring(0, data.Length - 1);

string responseValue = string.Empty;
try
{
if (!string.IsNullOrEmpty(data) && (Method == HttpVerb.POST))
{
byte[] bytes = Encoding.GetEncoding("iso-8859-1").GetBytes("{" + data + "}");
request.ContentLength = bytes.Length;

using (Stream writeStream = request.GetRequestStream())
writeStream.Write(bytes, 0, bytes.Length);
}

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
{
string message = string.Format("Request failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}

// grab the response
using (Stream responseStream = response.GetResponseStream())
if (responseStream != null)
using (StreamReader reader = new StreamReader(responseStream))
responseValue = reader.ReadToEnd();
}
}
catch (WebException wex)
{
if (wex.Message.Contains("(401)"))
BCNMessageBox.ShowError(string.Format(MM.SharedLabels.LoginFailed, EndPoint));
else
BCNMessageBox.ShowError(string.Join(Environment.NewLine, wex.Message, wex.Status));
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}

return responseValue;
}
}
Post Reply