diff --git a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj
index 58285ee69..1601425d3 100644
--- a/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj
+++ b/dotnet/src/dotnetcore/GxClasses/GxClasses.csproj
@@ -53,6 +53,8 @@
+
+
diff --git a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs
index e1acfec27..1b5873044 100644
--- a/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs
+++ b/dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs
@@ -1,6 +1,5 @@
using System.Runtime.CompilerServices;
-
[assembly: InternalsVisibleTo("GxClasses.Web")]
[assembly: InternalsVisibleTo("GxSearch")]
[assembly: InternalsVisibleTo("GxNetCoreStartup")]
diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs
new file mode 100644
index 000000000..a5d9b0a4f
--- /dev/null
+++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestAPIClient.cs
@@ -0,0 +1,361 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using GeneXus.Utils;
+using GeneXus.Http.Client;
+using System.Web;
+using GeneXus.Mime;
+#if NETCORE
+using System.Text.Json;
+using System.Text.Json.Serialization;
+#endif
+using System.IO;
+
+namespace GeneXus.Application
+{
+ public class GXRestAPIClient
+ {
+
+ public GXRestAPIClient()
+ {
+ Location = new GxLocation();
+ Location.BaseUrl = "api";
+ Location.Host = "www.example.com";
+ Location.ResourceName = "service";
+ Location.Port = 80;
+ }
+
+
+ private GxHttpClient httpClient = new GxHttpClient();
+ public GxLocation Location { get; set; }
+ public string Name { get; set; }
+ public int ErrorCode { get; set; }
+ public string ErrorMessage { get; set; }
+
+ public int StatusCode { get; set; }
+
+ public int ResponseCode { get => responseCode; set => responseCode = value; }
+ public string ResponseMessage { get => responseMessage; set => responseMessage = value; }
+ public string HttpMethod { get => httpMethod; set => httpMethod = value; }
+
+ public string protocol = "REST";
+
+ private string httpMethod = "GET";
+
+ private Dictionary _queryVars = new Dictionary();
+ private Dictionary _bodyVars = new Dictionary();
+ //private Dictionary _pathVars = new Dictionary();
+ private Dictionary _responseData = new Dictionary();
+
+ private string _contentType = "application/json; charset=utf-8";
+ private string _queryString = String.Empty;
+ private string _bodyString = String.Empty;
+
+ private int responseCode = 0;
+ private string responseMessage = String.Empty;
+
+ public void AddQueryVar(String varName, String varValue)
+ {
+ _queryVars[varName] = GXUtil.UrlEncode(varValue);
+ }
+
+ public void AddQueryVar(String varName, int varValue)
+ {
+ _queryVars[varName] = varValue.ToString();
+ }
+ public void AddQueryVar(String varName, short varValue)
+ {
+ _queryVars[varName] = varValue.ToString();
+ }
+
+ public void AddQueryVar(String varName, Decimal varValue)
+ {
+ _queryVars[varName] = varValue.ToString(System.Globalization.CultureInfo.InvariantCulture);
+ }
+
+ public void AddQueryVar(String varName, DateTime varValue)
+ {
+ _queryVars[varName] = varValue.ToString("yyyy-MM-dd");
+ }
+
+ public void AddQueryVar(String varName, DateTime varValue, bool hasMilliseconds)
+ {
+ string fmt = "yyyy-MM-ddTHH:mm:ss";
+ if (hasMilliseconds)
+ fmt = "yyyy-MM-ddTHH:mm:ss.fff";
+ _queryVars[varName] = varValue.ToString(fmt);
+ }
+ public void AddQueryVar(String varName, Guid varValue)
+ {
+ _queryVars[varName] = varValue.ToString();
+ }
+
+ public void AddQueryVar(String varName, Geospatial varValue)
+ {
+ _queryVars[varName] = GXUtil.UrlEncode(varValue.ToString());
+ }
+
+ public void AddQueryVar(String varName, bool varValue)
+ {
+ _queryVars[varName] = varValue.ToString();
+ }
+
+ public void AddQueryVar(String varName, GxUserType varValue)
+ {
+ if (varValue != null)
+ {
+ _bodyVars[varName] = varValue.ToJSonString();
+ }
+ }
+
+ public void AddQueryVar(String varName, IGxCollection varValue)
+ {
+ if (varValue != null)
+ {
+ _bodyVars[varName] = varValue.ToJSonString();
+ }
+ }
+
+ public void AddBodyVar(String varName, DateTime varValue)
+ {
+ _bodyVars[varName] = "\"" + varValue.ToString("yyyy-MM-dd") + "\"";
+ }
+
+ public void AddBodyVar(String varName, DateTime varValue, bool hasMilliseconds)
+ {
+ string fmt = "yyyy-MM-ddTHH:mm:ss";
+ if (hasMilliseconds)
+ fmt = "yyyy-MM-ddTHH:mm:ss.fff";
+ _bodyVars[varName] = "\"" + varValue.ToString(fmt) + "\"";
+ }
+
+ public void AddBodyVar(String varName, Decimal varValue)
+ {
+ _bodyVars[varName] = varValue.ToString(System.Globalization.CultureInfo.InvariantCulture);
+ }
+
+ public void AddBodyVar(String varName, string varValue)
+ {
+ _bodyVars[varName] = "\"" + varValue + "\"" ;
+ }
+ public void AddBodyVar(String varName, int varValue)
+ {
+ _bodyVars[varName] = varValue.ToString();
+ }
+ public void AddBodyVar(String varName, short varValue)
+ {
+ _bodyVars[varName] = varValue.ToString();
+ }
+
+ public void AddBodyVar(String varName, bool varValue)
+ {
+ _bodyVars[varName] = varValue.ToString();
+ }
+ public void AddBodyVar(String varName, Guid varValue)
+ {
+ _bodyVars[varName] = "\"" + varValue.ToString() + "\"";
+ }
+
+ public void AddBodyVar(String varName, Geospatial varValue)
+ {
+ _bodyVars[varName] = "\"" + varValue.ToString() + "\"";
+ }
+
+ public void AddBodyVar(String varName, GxUserType varValue)
+ {
+ if (varValue != null)
+ {
+ _bodyVars[varName] = varValue.ToJSonString();
+ }
+ }
+
+ public void AddBodyVar(String varName, IGxCollection varValue)
+ {
+ if (varValue != null)
+ {
+ _bodyVars[varName] = varValue.ToJSonString();
+ }
+ }
+
+ public string GetBodyString(string varName)
+ {
+ return GetJsonStr(varName);
+ }
+
+ public DateTime GetBodyDate(string varName)
+ {
+ return DateTime.ParseExact(GetJsonStr(varName), "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
+ }
+
+ public DateTime GetBodyDateTime(string varName, bool hasMilliseconds)
+ {
+ string fmt = "yyyy-MM-ddTHH:mm:ss";
+ if (hasMilliseconds)
+ fmt += ".fff";
+ return DateTime.ParseExact(GetJsonStr(varName), fmt,System.Globalization.CultureInfo.InvariantCulture);
+ }
+
+ public bool GetBodyBool(string varName)
+ {
+ return Boolean.Parse(GetJsonStr(varName));
+ }
+ public Guid GetBodyGuid(string varName)
+ {
+ return Guid.Parse(GetJsonStr(varName));
+ }
+
+ public Decimal GetBodyNum(string varName)
+ {
+ return Decimal.Parse( GetJsonStr(varName));
+ }
+
+ public int GetBodyInt(string varName)
+ {
+ return Int32.Parse(GetJsonStr(varName));
+ }
+
+ public short GetBodyShort(string varName)
+ {
+ return (short)Int16.Parse(GetJsonStr(varName));
+ }
+ public Geospatial GetBodyGeospatial(string varName)
+ {
+ Geospatial g = new Geospatial(GetJsonStr(varName));
+ if (Geospatial.IsNullOrEmpty(g))
+ {
+ g.FromGeoJSON(GetJsonStr(varName));
+ }
+ return g;
+ }
+
+ public string GetJsonStr(string varName)
+ {
+ string s = String.Empty;
+ if (_responseData.ContainsKey(varName.ToLower()))
+ {
+ s = _responseData[varName.ToLower()].ToString();
+ }
+ else if (_responseData.Count == 1 && _responseData.ContainsKey(String.Empty))
+ {
+ s = _responseData[String.Empty].ToString();
+ }
+ return s;
+ }
+
+ public T GetBodySdt(string varName) where T:GxUserType, new()
+ {
+ T sdt = new T();
+ if (_responseData.ContainsKey(varName.ToLower()))
+ {
+ sdt.FromJSonString(_responseData[varName.ToLower()].ToString(), null);
+ }
+ else if (_responseData.Count == 1 && _responseData.ContainsKey(String.Empty))
+ {
+ sdt.FromJSonString(_responseData[String.Empty].ToString(), null);
+ }
+ else if (_responseData.Count >= 1 && !_responseData.ContainsKey(varName.ToLower()))
+ {
+#if NETCORE
+ sdt.FromJSonString(JsonSerializer.Serialize(_responseData), null);
+#else
+ sdt.FromJSonString(JSONHelper.Serialize(_responseData), null);
+#endif
+ }
+ return sdt;
+ }
+
+ public GXBaseCollection GetBodySdtCollection(string varName) where T:GxUserType , new()
+ {
+ GXBaseCollection collection = new GXBaseCollection();
+ if (_responseData.ContainsKey(varName.ToLower()))
+ {
+ collection.FromJSonString(_responseData[varName.ToLower()].ToString(), null);
+ }
+ else if (_responseData.Count == 1 && _responseData.ContainsKey(String.Empty))
+ {
+ collection.FromJSonString(_responseData[String.Empty].ToString(), null);
+ }
+ return collection;
+ }
+
+ public GxSimpleCollection GetBodySimpleCollection(string varName)
+ {
+ GxSimpleCollection collection = new GxSimpleCollection();
+ if (_responseData.ContainsKey(varName.ToLower()))
+ {
+ collection.FromJSonString(_responseData[varName.ToLower()].ToString(), null);
+ }
+ else if (_responseData.Count == 1 && _responseData.ContainsKey(String.Empty))
+ {
+ collection.FromJSonString(_responseData[String.Empty].ToString(), null);
+ }
+ return collection;
+ }
+
+ public void AddUploadFile(string FilePath, string name)
+ {
+ httpClient.AddFile(FilePath, name);
+ string mimeType = MimeMapping.GetMimeMapping(FilePath);
+ _contentType = mimeType;
+ }
+
+ public void RestExecute()
+ {
+ this.ErrorCode = 0;
+ _queryString = String.Empty;
+ if (_queryVars.Count > 0)
+ {
+ string separator = "?";
+ foreach (string key in _queryVars.Keys)
+ {
+ _queryString += string.Format("{0}{1}={2}", separator, key, _queryVars[key]);
+ separator = "&";
+ }
+ }
+ _bodyString = String.Empty;
+ if (_bodyVars.Count > 0)
+ {
+ string separator = String.Empty;
+ foreach (string key in _bodyVars.Keys)
+ {
+ _bodyString += separator + "\"" + key + "\":" + _bodyVars[key];
+ separator = ",";
+ }
+ }
+ if (_bodyString.Length > 0)
+ {
+ _bodyString = "{" + _bodyString + "}";
+ httpClient.AddString(_bodyString);
+ httpClient.AddHeader("Content-Type", _contentType);
+ }
+ else
+ {
+ if (this.httpMethod == "POST" || this.httpMethod == "PUT")
+ {
+ _bodyString = "{}";
+ httpClient.AddString(_bodyString);
+ httpClient.AddHeader("Content-Type", _contentType);
+ }
+ }
+ string serviceuri = ((this.Location.Secure > 0) ? "https" : "http") + "://" + this.Location.Host;
+ serviceuri += (this.Location.Port != 80) ? ":" + this.Location.Port.ToString() : String.Empty;
+ serviceuri += "/" + this.Location.BaseUrl.TrimEnd('/').TrimStart('/') + "/" + this.Location.ResourceName;
+ serviceuri += _queryString;
+ httpClient.HttpClientExecute( this.HttpMethod, serviceuri);
+ if (httpClient.StatusCode >= 300 || httpClient.ErrCode > 0)
+ {
+ this.ErrorCode = (httpClient.ErrCode == 0)? 1: httpClient.ErrCode;
+ this.ErrorMessage = httpClient.ErrDescription;
+ this.StatusCode = httpClient.StatusCode;
+ _responseData = new Dictionary();
+ }
+ else
+ {
+ this.StatusCode = httpClient.StatusCode;
+ _responseData = GeneXus.Utils.RestAPIHelpers.ReadRestParameters(httpClient.ToString());
+ }
+ }
+ }
+}
diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs
index f2198a30d..d5ec2a42d 100644
--- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs
+++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXRestUtils.cs
@@ -2,9 +2,17 @@
using System.Web;
using GeneXus.Application;
using GeneXus.Http;
+using System.Collections.Generic;
#if NETCORE
using Microsoft.AspNetCore.Http;
+using System.Text.Json;
+using System.Text.Json.Serialization;
#endif
+using log4net;
+using System.IO;
+using Jayrock.Json;
+
+
namespace GeneXus.Utils
{
@@ -87,4 +95,50 @@ public class UploadCachedFile
public string fileExtension { get; set; }
}
+ internal class RestAPIHelpers
+ {
+ static readonly ILog log = log4net.LogManager.GetLogger(typeof(GeneXus.Utils.RestAPIHelpers));
+
+ public static Dictionary ReadRestParameters(string restData)
+ {
+ var bodyParameters = new Dictionary();
+ if (!String.IsNullOrEmpty(restData))
+ {
+ try
+ {
+ var data = JSONHelper.ReadJSON(restData);
+ if (data is JObject jobj)
+ {
+ foreach (string name in jobj.Names)
+ {
+ bodyParameters.Add(name.ToLower(), jobj[name]);
+ }
+ }
+ else if (data is JArray jArray)
+ {
+ bodyParameters.Add(string.Empty, jArray);
+ }
+ }
+ catch (Exception ex)
+ {
+ GXLogging.Error(log, ex, "Parsing error in Body ");
+ }
+ }
+ return bodyParameters;
+ }
+
+ public static Dictionary ReadRestBodyParameters(Stream stream)
+ {
+ var bodyParameters = new Dictionary();
+ using (StreamReader streamReader = new StreamReader(stream))
+ {
+ if (!streamReader.EndOfStream)
+ {
+ string json = streamReader.ReadToEnd();
+ return ReadRestParameters(json);
+ }
+ }
+ return bodyParameters;
+ }
+ }
}
diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GxObjectProperties.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GxObjectProperties.cs
new file mode 100644
index 000000000..cc735f09b
--- /dev/null
+++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GxObjectProperties.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using GeneXus.Utils;
+
+namespace GeneXus.Application
+{
+ public class GxObjectProperties
+ {
+ private GxLocation location = null;
+ private string errorMessage = String.Empty;
+ private int errorCode = 0;
+ private int statusCode = 0;
+
+ public GxLocation Location { get => location; set => location = value; }
+ public string ErrorMessage { get => errorMessage; set => errorMessage = value; }
+ public int ErrorCode { get => errorCode; set => errorCode = value; }
+ public int StatusCode { get => statusCode; set => statusCode = value; }
+ }
+
+ public class GxObjectsConfiguration {
+
+ private Dictionary _properties = new Dictionary();
+ public GxObjectProperties PropertiesFor(string objName)
+ {
+ if (!_properties.ContainsKey(objName))
+ _properties[objName] = new GxObjectProperties();
+ return _properties[objName];
+ }
+ }
+}
diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs
index 714da4d4e..a788e5b60 100644
--- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs
+++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs
@@ -186,7 +186,6 @@ private Dictionary ReadBodyParameters()
#endif
}
-
private Dictionary SetAlias(Dictionary bodyParameters, Dictionary varAlias)
{
Dictionary parameters = new Dictionary();
@@ -389,41 +388,11 @@ public virtual Task Patch(object key)
{
return MethodBodyExecute(key);
}
-
public Dictionary ReadRequestParameters(Stream stream)
{
- var bodyParameters = new Dictionary();
- using (StreamReader streamReader = new StreamReader(stream))
- {
- if (!streamReader.EndOfStream)
- {
- try
- {
- string json = streamReader.ReadToEnd();
- var data = JSONHelper.ReadJSON(json);
- JObject jobj = data as JObject;
- JArray jArray = data as JArray;
- if (jobj != null)
- {
- foreach (string name in jobj.Names)
- {
- bodyParameters.Add(name.ToLower(), jobj[name]);
- }
- }
- else if (jArray != null)
- {
- bodyParameters.Add(string.Empty, jArray);
- }
- }
- catch (Exception ex)
- {
- GXLogging.Error(log, ex, "Parsing error in Body ");
-
- }
- }
- }
- return bodyParameters;
+ return RestAPIHelpers.ReadRestBodyParameters(stream);
}
+
protected IDictionary ReadQueryParameters(Dictionary varAlias)
{
NameValueCollection query = _httpContext.Request.GetQueryString();