eBiz Soa Generic Components - Part 4 - Service Data Objects

If you haven’t read all the other parts of this series: Part 1 - Base, Part 2 - Data Query, Part 3 - Post Content, make sure to go read them because this component is the results of all three of them.

What is a Service Data Object (SDO)?

Service Data Objects was created to support the Aptify Web client ability to call stored procedures. You configure which stored procedures can be accessed through the Service Data Objects entity within Aptify. One of the primary examples of using this was to support the ability to have prompted drop down lists populate with values from a stored procedure instead of being manually configured. But it quickly expanded to being used to integrations and membership portals as Aptify clients started using the Soa.

The downfall though, the service was built for Aptify Web. It wasn’t built with the purpose of being used for integrations and membership portals. The response object… is fine. Not how I’d design it, but it works.

eBiz Soa Doesn’t Have SDO’s?

Well I wouldn’t say doesn’t. OTB box it doesn’t include the controller and setup for it. BUT, you totally can add it, it’s pretty easy. Add dlls, add the SDO controller record to the eBiz Soa’s controller configuration record. There you go, SDO’s through eBiz Soa.

We Can Do Better

What if we take the Data Query component and the Post Content component, and sprinkle in the SDO concept :D.

using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using PB.Rexies.AptifyBits;
using PB.Rexies.Data;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace SimplifyAptify.AptifyConfigs.Soa.EndpointComponents
{
    public class ServiceDataObjectEndpointComponent : PostContentEndpointComponent<Dictionary<string, object>>
    {
        protected override string RunCore()
        {
            Logger.LogInformation("ServiceDataObjectEndpointComponent");

            // Ensure & Get Post Content Data
            EnsureSetPostData();

            // Verify SDO Key
            if (!PostData.ContainsKey("SDO") || string.IsNullOrWhiteSpace(PostData["SDO"].ToString()))
            {
                throw new ArgumentException("SDO key is required.");
            }

            Logger.LogInformation("ServiceDataObjectEndpointComponent - Post Data: {PostData}", JsonConvert.SerializeObject(PostData, Formatting.Indented));

            // Get SDO Details
            var dataObjectName = string.Empty;
            var requiresPrinciple = true;

            var lstProps = new Dictionary<string, bool>();

            using (var reader = DataAction.ExecuteDataReaderParameterized(
                "spEndpointComponent_ServiceDataObjectEndpointComponent_sa",
                CommandType.StoredProcedure,
                DataAction.GetDataParameter("@SDO", SqlDbType.NVarChar, PostData["SDO"])
            ))
            {
                if (reader.Read())
                {
                    dataObjectName = reader.GetNullableString("DataObjectName") ?? string.Empty;
                    requiresPrinciple = reader.GetNullableBoolean("RequiresPrinciple") ?? true;
                }

                reader.NextResult();

                while (reader.Read())
                {
                    lstProps.Add(reader.GetString("Name"), reader.GetBoolean("IsRequired"));
                }
            }

            Logger.LogInformation("BaseEndpointProcessFlowComponent - DBObject: {DataObjectName} - Requires Principle: {RequiresPrinciple}", dataObjectName, requiresPrinciple);

            // Verify SDO Details
            if (string.IsNullOrWhiteSpace(dataObjectName))
            {
                throw new ArgumentException("Invalid SDO.");
            }

            if (requiresPrinciple)
            {
                EnsureAuthenticated();
            }

            if (lstProps.Count > 0)
            {
                var missing = lstProps.Where(p => p.Value)
                  .Select(p => p.Key)
                  .Except(PostData.Keys, StringComparer.OrdinalIgnoreCase);

                if (missing.Any())
                {
                    throw new ArgumentException($"Required properties ({string.Join(", ", missing)}) are missing.");
                }
            }

            // Execute Data Query for SDO
            var dataQueryComponent = new DataQueryEndpointComponent()
            {
                DataObjectName = dataObjectName,
                AuthenticatedPrincipalRecordId = AuthenticatedPrincipalRecordId
            };

            foreach (var propVal in PostData.Where(p => !p.Key.Equals("SDO", StringComparison.OrdinalIgnoreCase)))
            {
                dataQueryComponent.Properties.SetProperty(propVal.Key, propVal.Value);
            }

            dataQueryComponent.Config(Application);
            dataQueryComponent.Run();

            Properties.SetProperty(OutputEndpointComponentResponsePropertyName, dataQueryComponent.Properties.GetProperty(OutputEndpointComponentResponsePropertyName));
            Properties.SetProperty(EndpointComponentResponsePropertyName, dataQueryComponent.Properties.GetProperty(EndpointComponentResponsePropertyName));

            return SuccessResult;
        }
    }
}
/*
NAME: spEndpointComponent_ServiceDataObjectEndpointComponent_sa
DESC: Gets the details needed for the setup and validation of the Service Data Object Endpoint Component.
TYPE: Stored Procedure
GRANT: GRANT EXECUTE ON spEndpointComponent_ServiceDataObjectEndpointComponent_sa TO EndUsers
*/

CREATE PROCEDURE spEndpointComponent_ServiceDataObjectEndpointComponent_sa (
  @SDO NVARCHAR(250),
  @ServiceApplicationName NVARCHAR(250) = 'e-Business'
) AS BEGIN

  -- GET SDO ID
  DECLARE @SDOID INT
  SELECT TOP 1 @SDOID = sdo.ID

  FROM
    ServiceDataObject sdo

    INNER JOIN ServiceDataObjectApplication a ON
      a.ServiceDataObjectID = sdo.ID

    INNER JOIN ServiceApplication sa ON
      sa.ID = a.ServiceApplicationID
      AND sa.Name = @ServiceApplicationName

    INNER JOIN DBObject o ON
      o.ID = sdo.DatabaseObjectID
      AND o.Type = 'Stored Procedure'

  WHERE
    sdo.Name = @SDO


  -- SDO Details
  SELECT
    sdo.SQL [DataObjectName],
    sdo.EnableSecurity [RequiresPrinciple]

  FROM
    vwServiceDataObjects sdo

  WHERE
    sdo.ID = @SDOID


  -- SDO Properties
  SELECT
    p.Name,
    p.IsRequired

  FROM
    ServiceDataObjectParameter p

  WHERE
    p.ServiceDataObjectID = @SDOID

END

The Dictionary<string, object> allows us have a request body of flat property and value. An example call would look like:

{
  "SDO": "Data-Query-Examples",
  "Example": "MultipleDatasets",
  "LimitValue": 222
}

eBiz Soa JSON endpoint

Were not 100% done with the eBiz Soa JSON endpoints. We still need to add our SDO to the eBiz SAO.

SDO Endpoint

{
  "endpoints": {
    "ServiceDataObject": {
      "route": {
        "httpMethod": "POST",
        "segments": {
          "sdo": {
            "isLiteral": true,
            "type": "string"
          }
        }
      },
      "inputEntityDefinition": {
        "name": "ServiceDataObjectInputDefinition",
        "$ref": "<Path to folder as needed>/utilities.json#/InputFields/PostContent"
      },
      "outputEntityDefinition": null,
      "businessLogic": {
        "ServiceDataObjectBusinessLogic": {
          "executionType": "processFlow",
          "processFlowProperties": {
            "processFlowName": "<Name of your process flow that implements your SDO Component>",
            "processFlowParameters": {
              "AuthenticatedPrincipalRecordId": "@AuthenticatedAttributes.AuthenticatedPrincipalRecordId",
              "PostContent": "@Request.PostContent"
            }
          }
        }
      },
      "options": {
        "customOutput": true
      },
      "security": {
        "AllowAnonymous": {
          "$ref": "<Path to the OTB Common folder>/security.json#/allowAnonymous"
        }
      }
    }
  }
}

Utilities.json

{
  "InputFields": {
    "PostContent": {
      "fields": {
        "PostContent": {
          "type": "string",
          "input": {
            "httpMethods": [ "POST" ],
            "source": "body"
          }
        }
      }
    }
  }
}

Setup DB Object and SDO Record

Finally we need an Stored Procedure to execute through the SDO.

#1 - DB Object

/*
NAME: spEndpointComponent_DataQuery_Examples_sa
DESC: Examples of all the Data Query uses.
TYPE: Stored Procedure
GRANT: GRANT EXECUTE ON spEndpointComponent_DataQuery_Examples_sa TO EndUsers
*/

CREATE PROCEDURE spEndpointComponent_DataQuery_Examples_sa (
  @AuthenticatedPrincipalRecordId INT,
  @Example NVARCHAR(50) = NULL,
  @LimitValue NVARCHAR(50) = NULL
) AS BEGIN

  SELECT @Example = CASE
    WHEN @Example IS NULL OR RTRIM(@Example) = '' THEN 'SingleRecord'
    ELSE @Example
  END

  IF @Example = 'SingleRecord'
  BEGIN
    SELECT ID, FirstName, LastName
    FROM Person
    WHERE ID = @AuthenticatedPrincipalRecordId;
  END

  IF @Example = 'MultipleRecords'
  BEGIN
    SELECT TOP 10 ID, FirstName, LastName
    FROM Person
    ORDER BY NEWID()
  END

  IF @Example = 'SingleRecordTableConfig'
  BEGIN
    SELECT
      tables.TableName,
      tables.IsCollection

    FROM (
      SELECT 'Profile' [TableName], CAST(0 AS BIT) [IsCollection], 0 [Sequence]
    ) tables

    ;WITH OtherPersons AS (
      SELECT TOP 10 ID, FirstName, LastName, CAST(CASE WHEN ID = @AuthenticatedPrincipalRecordId THEN 1 ELSE 0 END AS BIT) [IsAuthenticatedPrincipalRecord]
      FROM Person
      WHERE ID != @AuthenticatedPrincipalRecordId
      ORDER BY NEWID()
    )
    SELECT TOP 10 ID, FirstName, LastName, CAST(CASE WHEN ID = @AuthenticatedPrincipalRecordId THEN 1 ELSE 0 END AS BIT) [IsAuthenticatedPrincipalRecord]
    FROM Person
    WHERE ID = @AuthenticatedPrincipalRecordId
    UNION ALL SELECT * FROM OtherPersons
  END

  IF @Example = 'MultipleRecordsTableConfig'
  BEGIN
    SELECT
      tables.TableName,
      tables.IsCollection

    FROM (
      SELECT 'Persons' [TableName], CAST(1 AS BIT) [IsCollection], 0 [Sequence]
    ) tables

    SELECT TOP 10 ID, FirstName, LastName
    FROM Person
    ORDER BY NEWID()
  END

  IF @Example = 'MultipleDatasets'
  BEGIN
    SELECT TOP 10 ID, FirstName, LastName
    FROM Person
    ORDER BY NEWID()

    SELECT c.Country, c.ISOCode, c.ID
    FROM Country c
    WHERE @LimitValue IS NULL OR CAST(c.ID AS NVARCHAR(50)) = @LimitValue

    SELECT RTRIM(sp.Abbreviation) [Abbr], sp.FullName, sp.CountryID
    FROM StateProvince sp
    WHERE @LimitValue IS NULL OR CAST(sp.CountryID AS NVARCHAR(50)) = @LimitValue
  END

  IF @Example = 'MultipleDatasetsTableConfig'
  BEGIN
    SELECT
      tables.TableName,
      tables.IsCollection

    FROM (
      SELECT 'Persons' [TableName], CAST(1 AS BIT) [IsCollection], 0 [Sequence]
      UNION SELECT 'Countries' [TableName], CAST(1 AS BIT) [IsCollection], 1 [Sequence]
      UNION SELECT 'StateProvinces' [TableName], CAST(1 AS BIT) [IsCollection], 2 [Sequence]
    ) tables

    ORDER BY tables.Sequence

    SELECT TOP 10 ID, FirstName, LastName
    FROM Person
    ORDER BY NEWID()

    SELECT c.Country, c.ISOCode, c.ID
    FROM Country c
    WHERE @LimitValue IS NULL OR CAST(c.ID AS NVARCHAR(50)) = @LimitValue

    SELECT RTRIM(sp.Abbreviation) [Abbr], sp.FullName, sp.CountryID
    FROM StateProvince sp
    WHERE @LimitValue IS NULL OR CAST(sp.CountryID AS NVARCHAR(50)) = @LimitValue
  END

  IF @Example = 'MultipleDatasetsSingleMultipleTableConfig'
  BEGIN
    SELECT
      tables.TableName,
      tables.IsCollection

    FROM (
      SELECT 'Persons' [TableName], CAST(0 AS BIT) [IsCollection], 0 [Sequence]
      UNION SELECT 'Countries' [TableName], CAST(1 AS BIT) [IsCollection], 1 [Sequence]
      UNION SELECT 'StateProvinces' [TableName], CAST(1 AS BIT) [IsCollection], 2 [Sequence]
    ) tables

    ORDER BY tables.Sequence

    SELECT ID, FirstName, LastName
    FROM Person
    WHERE ID = @AuthenticatedPrincipalRecordId;

    SELECT c.Country, c.ISOCode, c.ID
    FROM Country c
    WHERE @LimitValue IS NULL OR CAST(c.ID AS NVARCHAR(50)) = @LimitValue

    SELECT RTRIM(sp.Abbreviation) [Abbr], sp.FullName, sp.CountryID
    FROM StateProvince sp
    WHERE @LimitValue IS NULL OR CAST(sp.CountryID AS NVARCHAR(50)) = @LimitValue
  END

  IF @Example = 'ForJsonPath01'
  BEGIN
    SELECT (
      SELECT
        ID,
        FirstName,
        LastName,

        Countries = (
          SELECT c.Country, c.ISOCode, c.ID
          FROM Country c
          WHERE @LimitValue IS NULL OR CAST(c.ID AS NVARCHAR(50)) = @LimitValue
          FOR JSON PATH
        ),

        StateProvinces = (
          SELECT RTRIM(sp.Abbreviation) [Abbr], sp.FullName, sp.CountryID
          FROM StateProvince sp
          WHERE @LimitValue IS NULL OR CAST(sp.CountryID AS NVARCHAR(50)) = @LimitValue
          FOR JSON PATH
        )

      FROM
        Person

      WHERE
        ID = @AuthenticatedPrincipalRecordId

      FOR JSON PATH,
      INCLUDE_NULL_VALUES,
      WITHOUT_ARRAY_WRAPPER
    ) [JsonOutput]
  END

  IF @Example = 'ForJsonPath02'
  BEGIN
    SELECT (
      SELECT
        Profile = JSON_QUERY((
          SELECT
            ID,
            FirstName,
            LastName
          FROM Person
          WHERE ID = @AuthenticatedPrincipalRecordId
          FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
        )),
        Countries = (
          SELECT c.Country, c.ISOCode, c.ID
          FROM Country c
          WHERE @LimitValue IS NULL OR CAST(c.ID AS NVARCHAR(50)) = @LimitValue
          FOR JSON PATH
        ),
        StateProvinces = (
          SELECT RTRIM(sp.Abbreviation) [Abbr], sp.FullName, sp.CountryID
          FROM StateProvince sp
          WHERE @LimitValue IS NULL OR CAST(sp.CountryID AS NVARCHAR(50)) = @LimitValue
          FOR JSON PATH
        )

      FOR JSON PATH,
      INCLUDE_NULL_VALUES,
      WITHOUT_ARRAY_WRAPPER
    ) [JsonOutput]
  END

END

#2 - Service Data Object

Examples

Uses the Data-Query-Examples SDO from above, here are some examples of using it.

URL: POST /v1/sdo

Single Record

// Post Body
{
  "PostContent": "{\"SDO\":\"Data-Query-Examples\",\"Example\":\"SingleRecord\"}"
}

// Response
{
  "IsSuccess": true,
  "Data": {
    "ID": 2545,
    "FirstName": "Christopher",
    "LastName": "Hunter"
  },
  "Message": ""
}

Multiple Records

// Post Body
{
  "PostContent": "{\"SDO\":\"Data-Query-Examples\",\"Example\":\"MultipleRecords\"}"
}

// Response
{
  "IsSuccess": true,
  "Data": [
    {
      "ID": 641,
      "FirstName": "James",
      "LastName": "Miller"
    },
    {
      "ID": 390,
      "FirstName": "John",
      "LastName": "Jackson"
    },
    {
      "ID": 1188,
      "FirstName": "Brian",
      "LastName": "Hill"
    },
    {
      "ID": 2289,
      "FirstName": "Querida",
      "LastName": "Neal"
    },
    {
      "ID": 1542,
      "FirstName": "Alexander",
      "LastName": "Jones"
    },
    {
      "ID": 962,
      "FirstName": "Dahlia",
      "LastName": "Miller"
    },
    {
      "ID": 2257,
      "FirstName": "Herbert",
      "LastName": "Beck"
    },
    {
      "ID": 1223,
      "FirstName": "Mary",
      "LastName": "Neal"
    },
    {
      "ID": 1716,
      "FirstName": "Alexandra",
      "LastName": "Douglas"
    },
    {
      "ID": 1655,
      "FirstName": "Oliver",
      "LastName": "Baldwin"
    }
  ],
  "Message": ""
}

Multiple Datasets

// Post Body
{
  "PostContent": "{\"SDO\":\"Data-Query-Examples\",\"Example\":\"MultipleDatasets\",\"LimitValue\":222}"
}

//Response
{
  "IsSuccess": true,
  "Data": {
    "Table": [
      {
        "ID": 1161,
        "FirstName": "Athena",
        "LastName": "Baldwin"
      },
      {
        "ID": 257,
        "FirstName": "Christina",
        "LastName": "Byrd"
      },
      {
        "ID": 608,
        "FirstName": "Athena",
        "LastName": "Yukon"
      },
      {
        "ID": 1978,
        "FirstName": "Habika",
        "LastName": "Scott"
      },
      {
        "ID": 2272,
        "FirstName": "Yale",
        "LastName": "Jackson"
      },
      {
        "ID": 125,
        "FirstName": "Abraham",
        "LastName": "Yukon"
      },
      {
        "ID": 65,
        "FirstName": "Odessa",
        "LastName": "Tate"
      },
      {
        "ID": 43,
        "FirstName": "Paul",
        "LastName": "Holland"
      },
      {
        "ID": 924,
        "FirstName": "Rabea",
        "LastName": "Hale"
      },
      {
        "ID": 2077,
        "FirstName": "Christina",
        "LastName": "Beck"
      }
    ],
    "Table1": [
      {
        "Country": "United States",
        "ISOCode": "US",
        "ID": 222
      }
    ],
    "Table2": [
      {
        "Abbr": "AL",
        "FullName": "Alabama",
        "CountryID": 222
      },
      {
        "Abbr": "AK",
        "FullName": "Alaska",
        "CountryID": 222
      },
      {
        "Abbr": "AS",
        "FullName": "American Samoa",
        "CountryID": 222
      },
      {
        "Abbr": "AZ",
        "FullName": "Arizona",
        "CountryID": 222
      },
      ...........
      {
        "Abbr": "WA",
        "FullName": "Washington",
        "CountryID": 222
      },
      {
        "Abbr": "WV",
        "FullName": "West Virginia",
        "CountryID": 222
      },
      {
        "Abbr": "WI",
        "FullName": "Wisconsin",
        "CountryID": 222
      },
      {
        "Abbr": "WY",
        "FullName": "Wyoming",
        "CountryID": 222
      }
    ]
  },
  "Message": ""
}

Multiple Datasets w/Table Configuration

// Post Body
{
  "PostContent": "{\"SDO\":\"Data-Query-Examples\",\"Example\":\"MultipleDatasetsTableConfig\",\"LimitValue\":222}"
}

// Response
{
  "IsSuccess": true,
  "Data": {
    "Persons": [
      {
        "ID": 1769,
        "FirstName": "Aiesha",
        "LastName": "Mann"
      },
      {
        "ID": 2205,
        "FirstName": "Gary",
        "LastName": "Taylor"
      },
      {
        "ID": 1638,
        "FirstName": "Xanthe",
        "LastName": "Byrd"
      },
      {
        "ID": 53,
        "FirstName": "Baka",
        "LastName": "Garcia"
      },
      {
        "ID": 1451,
        "FirstName": "Kevin",
        "LastName": "Jackson"
      },
      {
        "ID": 1495,
        "FirstName": "David",
        "LastName": "Estevez"
      },
      {
        "ID": 2471,
        "FirstName": "Sebastian",
        "LastName": "O'Neal"
      },
      {
        "ID": 2364,
        "FirstName": "Noah",
        "LastName": "Harris"
      },
      {
        "ID": 2390,
        "FirstName": "Paige",
        "LastName": "Jones"
      },
      {
        "ID": 51,
        "FirstName": "Alexandra",
        "LastName": "Hale"
      }
    ],
    "Countries": [
      {
        "Country": "United States",
        "ISOCode": "US",
        "ID": 222
      }
    ],
    "StateProvinces": [
      {
        "Abbr": "AL",
        "FullName": "Alabama",
        "CountryID": 222
      },
      {
        "Abbr": "AK",
        "FullName": "Alaska",
        "CountryID": 222
      },
      {
        "Abbr": "AS",
        "FullName": "American Samoa",
        "CountryID": 222
      },
      {
        "Abbr": "AZ",
        "FullName": "Arizona",
        "CountryID": 222
      },
      ...........
      {
        "Abbr": "WA",
        "FullName": "Washington",
        "CountryID": 222
      },
      {
        "Abbr": "WV",
        "FullName": "West Virginia",
        "CountryID": 222
      },
      {
        "Abbr": "WI",
        "FullName": "Wisconsin",
        "CountryID": 222
      },
      {
        "Abbr": "WY",
        "FullName": "Wyoming",
        "CountryID": 222
      }
    ]
  },
  "Message": ""
}

Multiple Datasets Single and Multiple w/Table Configuration

// Post Body
{
  "PostContent": "{\"SDO\":\"Data-Query-Examples\",\"Example\":\"MultipleDatasetsSingleMultipleTableConfig\",\"LimitValue\":222}"
}

// Response
{
  "IsSuccess": true,
  "Data": {
    "Persons": {
      "ID": 2545,
      "FirstName": "Christopher",
      "LastName": "Hunter"
    },
    "Countries": [
      {
        "Country": "United States",
        "ISOCode": "US",
        "ID": 222
      }
    ],
    "StateProvinces": [
      {
        "Abbr": "AL",
        "FullName": "Alabama",
        "CountryID": 222
      },
      {
        "Abbr": "AK",
        "FullName": "Alaska",
        "CountryID": 222
      },
      {
        "Abbr": "AS",
        "FullName": "American Samoa",
        "CountryID": 222
      },
      {
        "Abbr": "AZ",
        "FullName": "Arizona",
        "CountryID": 222
      },
      ...........
      {
        "Abbr": "WA",
        "FullName": "Washington",
        "CountryID": 222
      },
      {
        "Abbr": "WV",
        "FullName": "West Virginia",
        "CountryID": 222
      },
      {
        "Abbr": "WI",
        "FullName": "Wisconsin",
        "CountryID": 222
      },
      {
        "Abbr": "WY",
        "FullName": "Wyoming",
        "CountryID": 222
      }
    ]
  },
  "Message": ""
}

For Json Path - 01

// Post Body
{
  "PostContent": "{\"SDO\":\"Data-Query-Examples\",\"Example\":\"ForJsonPath01\",\"LimitValue\":222}"
}

// Response
{
  "IsSuccess": true,
  "Data": {
    "ID": 2545,
    "FirstName": "Christopher",
    "LastName": "Hunter",
    "Countries": [
      {
        "Country": "Andorra",
        "ISOCode": "AD",
        "ID": 1
      },
      {
        "Country": "United Arab Emirates",
        "ISOCode": "AE",
        "ID": 2
      },
      {
        "Country": "Afghanistan",
        "ISOCode": "AF",
        "ID": 3
      },
      ................
      {
        "Country": "Canada",
        "ISOCode": "CA",
        "ID": 36
      },
      ................
      {
        "Country": "United States",
        "ISOCode": "US",
        "ID": 222
      },
      ................
      {
        "Country": "Serbia",
        "ISOCode": "RS",
        "ID": 247
      },
      {
        "Country": "West Bank",
        "ISOCode": "WE",
        "ID": 248
      }
    ],
    "StateProvinces": [
      {
        "Abbr": "AB",
        "FullName": "Alberta",
        "CountryID": 36
      },
      {
        "Abbr": "BC",
        "FullName": "British Columbia",
        "CountryID": 36
      },
      {
        "Abbr": "MB",
        "FullName": "Manitoba",
        "CountryID": 36
      },
      {
        "Abbr": "NB",
        "FullName": "New Brunswick",
        "CountryID": 36
      },
      {
        "Abbr": "NL",
        "FullName": "Newfoundland and Labrador",
        "CountryID": 36
      },
      {
        "Abbr": "NT",
        "FullName": "Northwest Territories",
        "CountryID": 36
      },
      {
        "Abbr": "NS",
        "FullName": "Nova Scotia",
        "CountryID": 36
      },
      {
        "Abbr": "NU",
        "FullName": "Nunavut",
        "CountryID": 36
      },
      {
        "Abbr": "ON",
        "FullName": "Ontario",
        "CountryID": 36
      },
      ................
      {
        "Abbr": "SA",
        "FullName": "South Australia",
        "CountryID": 14
      },
      {
        "Abbr": "TAS",
        "FullName": "Tasmania",
        "CountryID": 14
      },
      {
        "Abbr": "VIC",
        "FullName": "Victoria",
        "CountryID": 14
      },
      {
        "Abbr": "WA",
        "FullName": "Western Australia",
        "CountryID": 14
      }
    ]
  },
  "Message": ""
}

For Json Path - 02

// Post Body
{
  "PostContent": "{\"SDO\":\"Data-Query-Examples\",\"Example\":\"ForJsonPath02\",\"LimitValue\":222}"
}

// Response
{
  "IsSuccess": true,
  "Data": {
    "Profile": {
      "ID": 2545,
      "FirstName": "Christopher",
      "LastName": "Hunter"
    },
    "Countries": [
      {
        "Country": "Canada",
        "ISOCode": "CA",
        "ID": 36
      }
    ],
    "StateProvinces": [
      {
        "Abbr": "AB",
        "FullName": "Alberta",
        "CountryID": 36
      },
      {
        "Abbr": "BC",
        "FullName": "British Columbia",
        "CountryID": 36
      },
      {
        "Abbr": "MB",
        "FullName": "Manitoba",
        "CountryID": 36
      },
      {
        "Abbr": "NB",
        "FullName": "New Brunswick",
        "CountryID": 36
      },
      {
        "Abbr": "NL",
        "FullName": "Newfoundland and Labrador",
        "CountryID": 36
      },
      {
        "Abbr": "NT",
        "FullName": "Northwest Territories",
        "CountryID": 36
      },
      ................
      {
        "Abbr": "QC",
        "FullName": "Quebec",
        "CountryID": 36
      },
      {
        "Abbr": "SK",
        "FullName": "Saskatchewan",
        "CountryID": 36
      },
      {
        "Abbr": "YT",
        "FullName": "Yukon",
        "CountryID": 36
      }
    ]
  },
  "Message": ""
}

Simpler eBiz Soa

That’s it. The combination of these 3 components should make setting up and implementing endpoints simpler and faster for you.

NOTE: ALWAYS remember security and user context. Just because it’s easier to generate your endpoints, it’s no excuse to become a lazy developer.

If you haven’t join yet, make sure to join us on the Aptify Developer Round-Table every other month.

Enjoy.

Aptify Clients

Continue the conversation on the Community Forums.