diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln
index a76069393..ac114bd0e 100644
--- a/dotnet/DotNetStandardClasses.sln
+++ b/dotnet/DotNetStandardClasses.sln
@@ -200,6 +200,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestMockDBAccess", "src\ext
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneXus.Programs.Common", "src\extensions\Azure\test\GeneXus.Programs.Common\GeneXus.Programs.Common.csproj", "{DCEC0B38-93B6-4003-81E6-9FBC2BB4F163}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "apiattractions", "src\extensions\Azure\test\apiattractions\apiattractions.csproj", "{E85FDB0F-FA81-4CDD-8BF3-865269CE2DB3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -486,6 +488,10 @@ Global
{DCEC0B38-93B6-4003-81E6-9FBC2BB4F163}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DCEC0B38-93B6-4003-81E6-9FBC2BB4F163}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DCEC0B38-93B6-4003-81E6-9FBC2BB4F163}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E85FDB0F-FA81-4CDD-8BF3-865269CE2DB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E85FDB0F-FA81-4CDD-8BF3-865269CE2DB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E85FDB0F-FA81-4CDD-8BF3-865269CE2DB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E85FDB0F-FA81-4CDD-8BF3-865269CE2DB3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -582,6 +588,7 @@ Global
{C16BD5A9-4412-4B91-BB70-5C88B7AAE675} = {5045873B-E7CF-4317-94C1-0EF8623D23FA}
{B01A243D-C012-4BEB-BAA9-E1D9AC1468C8} = {C16BD5A9-4412-4B91-BB70-5C88B7AAE675}
{DCEC0B38-93B6-4003-81E6-9FBC2BB4F163} = {7BA5A2CE-7992-4F87-9D84-91AE4D046F5A}
+ {E85FDB0F-FA81-4CDD-8BF3-865269CE2DB3} = {7BA5A2CE-7992-4F87-9D84-91AE4D046F5A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E18684C9-7D76-45CD-BF24-E3944B7F174C}
diff --git a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs
index b1deaadaa..192d77fd2 100644
--- a/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs
+++ b/dotnet/src/dotnetcore/GxClasses.Web/Middleware/GXRouting.cs
@@ -188,7 +188,8 @@ public Task ProcessRestRequest(HttpContext context)
string path = context.Request.Path.ToString();
string actualPath = string.Empty;
- if (path.Contains($"/{restBaseURL}") || ServiceInPath(path, out actualPath) || (AzureRuntime && path.Contains(oauthRoute)))
+ bool isServiceInPath = ServiceInPath(path, out actualPath);
+ if (path.Contains($"/{restBaseURL}") || isServiceInPath || (AzureRuntime && path.Contains(oauthRoute)))
{
string controllerWithParms = string.Empty;
if (!AzureRuntime)
diff --git a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj
index 06bc6b9b2..f3d9485b2 100644
--- a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj
+++ b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/AzureFunctionsTest.csproj
@@ -19,6 +19,7 @@
+
@@ -31,6 +32,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/HttpTriggerTest.cs b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/HttpTriggerTest.cs
index 90dd77fdf..bed11eb6b 100644
--- a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/HttpTriggerTest.cs
+++ b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/HttpTriggerTest.cs
@@ -18,6 +18,42 @@ namespace Extensions.AzureFunctions.Test
{
public class HttpTriggerTest
{
+ [Fact]
+ public void HttpApiObjectTest()
+ {
+ try
+ {
+ ServiceCollection serviceCollection = new ServiceCollection();
+ serviceCollection.AddScoped();
+ ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
+
+ Mock context = new Mock();
+ context.SetupProperty(c => c.InstanceServices, serviceProvider);
+
+ context.SetupGet(c => c.FunctionId).Returns("6202c88748614a51851a40fa6a4366e6");
+ context.SetupGet(c => c.FunctionDefinition.Name).Returns("listattractions");
+ context.SetupGet(c => c.InvocationId).Returns("6a871dbc3cb74a9fa95f05ae63505c2c");
+
+ MockHttpRequestData request = new MockHttpRequestData(
+ context.Object,
+ new Uri("http://localhost/APIAttractions/ListAttractions"));
+
+ HttpTriggerHandler function = new HttpTriggerHandler(new GXRouting(String.Empty), null);
+ HttpResponseData response = function.Run(request, context.Object);
+ Assert.NotNull(response);
+ Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
+ response.Body.Seek(0, SeekOrigin.Begin);
+ StreamReader reader = new StreamReader(response.Body);
+ string responseBody = reader.ReadToEnd();
+ Assert.NotEmpty(responseBody);
+
+ }
+ catch (Exception ex)
+ {
+ throw new Exception("Exception should not be thrown.", ex);
+ }
+
+ }
[Fact]
public void HttpTest()
{
diff --git a/dotnet/src/extensions/Azure/test/AzureFunctionsTest/private/apiattractions.grp.json b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/private/apiattractions.grp.json
new file mode 100644
index 000000000..ac00ab8a5
--- /dev/null
+++ b/dotnet/src/extensions/Azure/test/AzureFunctionsTest/private/apiattractions.grp.json
@@ -0,0 +1,17 @@
+{
+"ObjectType":"ServiceGroup",
+"Name":"APIAttractions",
+"BasePath":"APIAttractions",
+"Mappings":
+[
+{
+"Name":"listattractions",
+"Bodystyle":"Wrapped",
+"VariableAlias": [],
+"ServiceMethod":"gxep_listattractions",
+"Implementation":"AttractionsDP",
+"Verb":"GET",
+"PathRegexp":"listattractions",
+"Path":"listattractions"
+
+}]}
\ No newline at end of file
diff --git a/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtAttractionOut_Attraction.cs b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtAttractionOut_Attraction.cs
new file mode 100644
index 000000000..f86eb5251
--- /dev/null
+++ b/dotnet/src/extensions/Azure/test/GeneXus.Programs.Common/type_SdtAttractionOut_Attraction.cs
@@ -0,0 +1,196 @@
+/*
+ File: type_SdtAttractionOut_Attraction
+ Description: AttractionOut
+ Author: Nemo 🐠 for C# (.NET) version 17.0.10.160814
+ Program type: Callable routine
+ Main DBMS:
+*/
+using System;
+using System.Collections;
+using GeneXus.Utils;
+using GeneXus.Resources;
+using GeneXus.Application;
+using GeneXus.Metadata;
+using GeneXus.Cryptography;
+using GeneXus.Encryption;
+using GeneXus.Http.Client;
+using GeneXus.Http.Server;
+using System.Reflection;
+using System.Xml.Serialization;
+using System.Runtime.Serialization;
+
+
+namespace GeneXus.Programs
+{
+ [XmlRoot(ElementName="Attraction")]
+ [XmlType(TypeName="Attraction" , Namespace="TestServerlessGAM" )]
+ [Serializable]
+ public class SdtAttractionOut_Attraction : GxUserType
+ {
+ public SdtAttractionOut_Attraction( )
+ {
+ /* Constructor for serialization */
+ gxTv_SdtAttractionOut_Attraction_Attractionname = "";
+
+ }
+
+ public SdtAttractionOut_Attraction(IGxContext context)
+ {
+ this.context = context;
+ initialize();
+ }
+
+ #region Json
+ private static Hashtable mapper;
+ public override string JsonMap(string value)
+ {
+ if (mapper == null)
+ {
+ mapper = new Hashtable();
+ }
+ return (string)mapper[value]; ;
+ }
+
+ public override void ToJSON()
+ {
+ ToJSON(true) ;
+ return;
+ }
+
+ public override void ToJSON(bool includeState)
+ {
+ AddObjectProperty("AttractionId", gxTpr_Attractionid, false);
+
+
+ AddObjectProperty("AttractionName", gxTpr_Attractionname, false);
+
+ return;
+ }
+ #endregion
+
+ #region Properties
+
+ [SoapElement(ElementName="AttractionId")]
+ [XmlElement(ElementName="AttractionId")]
+ public short gxTpr_Attractionid
+ {
+ get {
+ return gxTv_SdtAttractionOut_Attraction_Attractionid;
+ }
+ set {
+ gxTv_SdtAttractionOut_Attraction_Attractionid = value;
+ SetDirty("Attractionid");
+ }
+ }
+
+
+
+
+ [SoapElement(ElementName="AttractionName")]
+ [XmlElement(ElementName="AttractionName")]
+ public string gxTpr_Attractionname
+ {
+ get {
+ return gxTv_SdtAttractionOut_Attraction_Attractionname;
+ }
+ set {
+ gxTv_SdtAttractionOut_Attraction_Attractionname = value;
+ SetDirty("Attractionname");
+ }
+ }
+
+
+
+ public override bool ShouldSerializeSdtJson()
+ {
+ return true;
+ }
+
+
+
+ #endregion
+
+ #region Initialization
+
+ public void initialize( )
+ {
+ gxTv_SdtAttractionOut_Attraction_Attractionname = "";
+ return ;
+ }
+
+
+
+ #endregion
+
+ #region Declaration
+
+ protected short gxTv_SdtAttractionOut_Attraction_Attractionid;
+
+
+ protected string gxTv_SdtAttractionOut_Attraction_Attractionname;
+
+
+
+ #endregion
+ }
+ #region Rest interface
+ [DataContract(Name=@"Attraction", Namespace="TestServerlessGAM")]
+ public class SdtAttractionOut_Attraction_RESTInterface : GxGenericCollectionItem, System.Web.SessionState.IRequiresSessionState
+ {
+ public SdtAttractionOut_Attraction_RESTInterface( ) : base()
+ {
+ }
+
+ public SdtAttractionOut_Attraction_RESTInterface( SdtAttractionOut_Attraction psdt ) : base(psdt)
+ {
+ }
+
+ #region Rest Properties
+ [DataMember(Name="AttractionId", Order=0)]
+ public short gxTpr_Attractionid
+ {
+ get {
+ return sdt.gxTpr_Attractionid;
+
+ }
+ set {
+ sdt.gxTpr_Attractionid = value;
+ }
+ }
+
+ [DataMember(Name="AttractionName", Order=1)]
+ public string gxTpr_Attractionname
+ {
+ get {
+ return StringUtil.RTrim( sdt.gxTpr_Attractionname);
+
+ }
+ set {
+ sdt.gxTpr_Attractionname = value;
+ }
+ }
+
+
+ #endregion
+
+ public SdtAttractionOut_Attraction sdt
+ {
+ get {
+ return (SdtAttractionOut_Attraction)Sdt;
+ }
+ set {
+ Sdt = value;
+ }
+ }
+
+ [OnDeserializing]
+ void checkSdt( StreamingContext ctx )
+ {
+ if ( sdt == null )
+ {
+ sdt = new SdtAttractionOut_Attraction() ;
+ }
+ }
+ }
+ #endregion
+}
\ No newline at end of file
diff --git a/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.cs b/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.cs
new file mode 100644
index 000000000..aadbc0a40
--- /dev/null
+++ b/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.cs
@@ -0,0 +1,93 @@
+using GeneXus.Application;
+using GeneXus.Data;
+using GeneXus.Http;
+using GeneXus.Procedure;
+using GeneXus.Utils;
+namespace GeneXus.Programs
+{
+ public class apiattractions : GXProcedure
+ {
+ protected override bool IntegratedSecurityEnabled
+ {
+ get
+ {
+ return true;
+ }
+
+ }
+
+ protected override GAMSecurityLevel IntegratedSecurityLevel
+ {
+ get
+ {
+ return GAMSecurityLevel.SecurityLow;
+ }
+
+ }
+
+ public apiattractions()
+ {
+ context = new GxContext();
+ dsGAM = context.GetDataStore("GAM");
+ dsDefault = context.GetDataStore("Default");
+ IsMain = true;
+ IsApiObject = true;
+ }
+
+ public apiattractions(IGxContext context)
+ {
+ this.context = context;
+ IsMain = false;
+ IsApiObject = true;
+ dsGAM = context.GetDataStore("GAM");
+ dsDefault = context.GetDataStore("Default");
+ }
+
+ public void execute()
+ {
+ executePrivate();
+ }
+
+ void executePrivate()
+ {
+ /* GeneXus formulas */
+ /* Output device settings */
+ this.cleanup();
+ }
+
+ public void gxep_listattractions(out GXBaseCollection aP0_AttractionOut)
+ {
+
+ initialize();
+ initialized = 1;
+ GXBaseCollection Gxm2rootcol = new GXBaseCollection(context, "Attraction", "TestServerlessGAM");
+ /* ListAttractions Constructor */
+ SdtAttractionOut_Attraction Gxm1attractionout = new SdtAttractionOut_Attraction(context);
+ Gxm2rootcol.Add(Gxm1attractionout, 0);
+ Gxm1attractionout.gxTpr_Attractionid = 1;
+ Gxm1attractionout.gxTpr_Attractionname = "AttractionName";
+
+ aP0_AttractionOut=Gxm2rootcol;
+ }
+
+ public override void cleanup()
+ {
+ CloseOpenCursors();
+ }
+
+ protected void CloseOpenCursors()
+ {
+ }
+
+ public override void initialize()
+ {
+ /* GeneXus formulas. */
+ context.Gx_err = 0;
+ }
+
+ protected short initialized;
+ protected IGxDataStore dsGAM;
+ protected IGxDataStore dsDefault;
+ }
+
+}
diff --git a/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj b/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj
new file mode 100644
index 000000000..12c8a31ed
--- /dev/null
+++ b/dotnet/src/extensions/Azure/test/apiattractions/apiattractions.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+