diff --git a/Developer Samples/Runtime Overrides/Runtime Overrides CI CD example Script.md b/Developer Samples/Runtime Overrides/Runtime Overrides CI CD example Script.md deleted file mode 100644 index 3becb56..0000000 --- a/Developer Samples/Runtime Overrides/Runtime Overrides CI CD example Script.md +++ /dev/null @@ -1,39 +0,0 @@ -# Starter pipeline -# Start with a minimal pipeline that you can customize to build and deploy your code. -# Add steps that build, run tests, deploy, and more: -# https://aka.ms/yaml - -trigger: -- master - -pool: - vmImage: 'ubuntu-latest' - -steps: -- script: echo Hello, world! - displayName: 'Run a one-line script' - -- script: | - echo Add other tasks to build, test, and deploy your project. - echo See https://aka.ms/yaml - displayName: 'Run a multi-line script' - -- script: | - curl -X GET "<-- your GET URL -->" -H "accept: application/json" -H "Authorization: APIKEY <--your API key-->" - displayName: 'get a list of current overrides' - -- script: | - curl -X POST "<-- your POST URL -->" -H "accept: application/json" -H "Authorization: APIKEY <--your API key-->" -H "Content-Type: application/json" -d "{\"type\":\"DatabaseConnection\",\"property\":\"ConnectionString\",\"name\":\"testName\",\"value\":\"testValue\"}" - displayName: 'set the testName connection string to testValue' - -- script: | - curl -X GET "<-- your GET URL -->" -H "accept: application/json" -H "Authorization: APIKEY <--your API key-->" - displayName: 'get a list of overrides after setting' - -- script: | - curl -X DELETE "<-- your DELETE URL -->" -H "accept: application/json" -H "Authorization: APIKEY <--your API key-->" -H "Content-Type: application/json" -d "{\"type\":\"DatabaseConnection\",\"property\":\"ConnectionString\",\"name\":\"testName\"}" - displayName: 'delete the override we just created' - -- script: | - curl -X GET "<-- your GET URL -->" -H "accept: application/json" -H "Authorization: APIKEY <--your API key-->" - displayName: 'get a list of overrides after deleting' diff --git a/Developer Samples/RuntimeOverrides/README.md b/Developer Samples/RuntimeOverrides/README.md new file mode 100644 index 0000000..d16b473 --- /dev/null +++ b/Developer Samples/RuntimeOverrides/README.md @@ -0,0 +1,185 @@ +# Runtime Overrides + +Runtime overrides may override End Point and Data Element settings that differ from what was originally authored in a Rule Application. +This can be useful when deploying an application to different environments. + +Overrides may be specified either using irSDK from the `RuleSession.Overrides` property, or via .config file ``. + +The following End Points may be overridden: +- Database Connection +- Rest Service +- Web Service +- SendMail Service +- XML Schema + +The following Data Elements may be overridden: +- Inline Value List +- Inline Table +- Inline XML Document +- SQL Query +- XPath Query +- REST Operation + +--- +## irSDK Override Mechanism +When creating a RuleSession for executing rules, overrides may be specified prior to execution. + +For example: + +``` +using (RuleSession session = new RuleSession(ruleApp)) +{ + session.Overrides.OverrideRestOperationUriTemplate("operation1", "api/v2/invoice"); + session.CreateEntity("Invoice"); + session.ApplyRules(); +} +``` + +--- +## Configuration Override Mechanism +Using the `` in the application's .config file, overrides may be applied declaratively instead of adding irSDK code. + +These `` may be extended using [Configuration Builders](https://github.com/aspnet/MicrosoftConfigurationBuilders) to read configuration from external sources such as Environment Variables, JSON files, or Azure KeyVault. + +The `` follow a key/value pattern. The key is the identifier of the override, and the value is the new value for the Runtime to use. + +For example: + +``` + + + + + +``` + +This illustrates the equivalent of the irSDK override example listed above. + +### Key Format +The appSetting key follows the following format: + +`inrule:runtime:overrides:::` + +- `` is the name of the End Point or Data Element +- `` is the type of End Point or Data Element (see list below) +- `` is the property of the type being overridden (see list below) + +**Note: These overrides will apply to End Points and Data Elements with the same name across different Rule Applications.** + +The `` component is **case-sensitive**. + +The `` and `` components are **not case-sensitive**. The combination of type/property may be selected from the following: + +### End Points +| Type | Property | +| ---- | -------- | +| DatabaseConnection | ConnectionString | +| SendMailServer | ServerAddress | +| XmlDocument | XmlPath | +| XmlSchema | XsdPath | +| | EnableXsdValidation | +| WebService | WsdlUrl | +| | ServiceUriOverride | +| | MaxReceivedMessageSize | +| RestService | RootUrl | +| | AllowUntrustedCertificates | +| | AuthenticationType | +| | Username | +| | Password | +| | Domain | +| | X509CertificatePath | +| | X509CertificatePassword | + +### Data Elements + +| Name | Property | +| ---- | -------- | +| ValueList | ValueListItems* | +| Table | TableSettings* | +| XPathDocument | InlineXml | +| SqlQuery | Query | +| RestOperation | UriTemplate | +| | Body | +| | Headers* | + +_*see special handling below_ + +**Note: All appSetting values must be HTML-safe, so any values containing characters such as '&', '<', '>', '\\"' should first be passed through an HTML encoder.** + +For example: + +``` +const string unencodedValue = @"This is a \"test\" & should be encoded"; + +Console.WriteLine("Unencoded Value: " + unencodedValue); +Console.WriteLine("Encoded Value: " + System.Net.WebUtility.HtmlEncode(unencodedValue)); +``` + +The above should output the following: + +``` +Unencoded Value: This is a "test" & should be encoded +Encoded Value: <InlineXml><Value1>This is a "test" & should be encoded</Value1></InlineXml> +``` + +#### ValueListItems Serialization +The value for ValueListItems uses a custom XML format, which must be HTML encoded for use as the value. + +For example: + +``` +const string valueListItems = +@" + + Value1 + Value One + + + Value2 + + + Value3 + +"; + +var value = System.Net.WebUtility.HtmlEncode(valueListItems); +``` + +#### TableSettings Serialization +The value of TableSettings configuration must use irSDK to XML Serialize an instance of `InRule.Repository.TableSettings`. This must then be HTML encoded for use as the value. + +For example: + +``` +var tableSettings = ruleAppDef.DataElements["table1"].TableSettings; +var xs = new XmlSerializer(typeof("InRule.Repository.TableSettings)); +var sb = new StringBuilder(); +using (var writer = new StringWriter(sb)) +{ + xs.Serialize(writer, tableSettings); +} + +var value = System.Net.WebUtility.HtmlEncode(sb.ToString()); +``` + +#### REST Operation Headers +The Headers are a collection of name/value pairs. Any number of headers may be applied. To simulate a collection, the appSetting key is extended to include the header name. + +For example: +``` + + + + + + + + + +``` + +--- +## Samples +The 2 samples illustrate how the REST operation may be overridden by both irSDK and .config ``: +- [RuntimeOverridesViaSdk](RuntimeOverridesViaSdk/) +- [RuntimeOverridesViaConfig](RuntimeOverridesViaConfig/) diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverrides.sln b/Developer Samples/RuntimeOverrides/RuntimeOverrides.sln new file mode 100644 index 0000000..eef6200 --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverrides.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32126.317 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RuntimeOverridesViaSdk", "RuntimeOverridesViaSdk\RuntimeOverridesViaSdk.csproj", "{5E9273F5-548A-4813-9499-5201B2160060}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RuntimeOverridesViaConfig", "RuntimeOverridesViaConfig\RuntimeOverridesViaConfig.csproj", "{AD7153D5-AD79-4928-AF2E-41CCAD584EE5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{55B8A9D2-B845-469F-B26D-EAAB2866E33F}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5E9273F5-548A-4813-9499-5201B2160060}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5E9273F5-548A-4813-9499-5201B2160060}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5E9273F5-548A-4813-9499-5201B2160060}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5E9273F5-548A-4813-9499-5201B2160060}.Release|Any CPU.Build.0 = Release|Any CPU + {AD7153D5-AD79-4928-AF2E-41CCAD584EE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD7153D5-AD79-4928-AF2E-41CCAD584EE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD7153D5-AD79-4928-AF2E-41CCAD584EE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AD7153D5-AD79-4928-AF2E-41CCAD584EE5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FCBB9BA7-F634-45F4-9797-72E3AA9A6F7A} + EndGlobalSection +EndGlobal diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/App.config b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/App.config new file mode 100644 index 0000000..827792c --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/App.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/InProcessWebServer.cs b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/InProcessWebServer.cs new file mode 100644 index 0000000..9bee657 --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/InProcessWebServer.cs @@ -0,0 +1,86 @@ +using System; +using System.Net; + +namespace RuntimeOverridesViaConfig +{ + public sealed class InProcessWebServer : IDisposable + { + private const int HttpPort = 9595; + + private readonly Action _processRequest; + private readonly HttpListener _httpListener; + + public InProcessWebServer(Action processRequest) + { + _processRequest = processRequest; + _httpListener = new HttpListener { AuthenticationSchemes = AuthenticationSchemes.Anonymous }; + _httpListener.Prefixes.Add(RootUrl); + _httpListener.Start(); + Result = _httpListener.BeginGetContext(WebRequestCallback, _httpListener); + } + + public static string RootUrl => $"http://localhost:{HttpPort}/"; + + public IAsyncResult Result { get; private set; } + + public HttpListenerRequest Request { get; private set; } + + public void Dispose() + { + if (_httpListener == null) return; + + lock (_httpListener) + { + try + { + ((IDisposable)_httpListener).Dispose(); + } + catch + { + } + } + } + + private void WebRequestCallback(IAsyncResult result) + { + // Avoid accessing HttpListener while/after it has been disposed + lock (_httpListener) + { + if (!_httpListener.IsListening) return; + + try + { + HttpListenerContext context = _httpListener.EndGetContext(result); + + Request = context.Request; + + try + { + if (_processRequest == null) + { + context.Response.StatusCode = (int)HttpStatusCode.OK; + context.Response.Headers.Add(HttpResponseHeader.ContentType, "text/plain"); + } + else + { + _processRequest(context); + } + } + finally + { + context.Response.OutputStream.Close(); + } + } + catch (Exception ex) + { + Console.WriteLine($"[Server] - Error: {ex.Message}"); + } + finally + { + // Set up the next context + Result = _httpListener.BeginGetContext(WebRequestCallback, _httpListener); + } + } + } + } +} diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/Program.cs b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/Program.cs new file mode 100644 index 0000000..d8ce54d --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/Program.cs @@ -0,0 +1,81 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using InRule.Repository; +using InRule.Repository.EndPoints; +using InRule.Repository.RuleElements; +using InRule.Runtime; + +namespace RuntimeOverridesViaConfig +{ + internal class Program + { + static void Main(string[] args) + { + var ruleAppDef = CreateRuleApplication(out var operationDef, out var e1Def); + + using (new InProcessWebServer(ProcessRequest)) + { + Console.WriteLine("--- Config Overrides ----------------------------"); + using (RuleSession session = new RuleSession(ruleAppDef)) + { + session.CreateEntity(e1Def.Name); + session.ApplyRules(); + } + } + } + + private static RuleApplicationDef CreateRuleApplication(out DataElementDef restOperationDef, out EntityDef e1Def) + { + var ruleAppDef = new RuleApplicationDef(); + var restServiceDef = ruleAppDef.EndPoints.Add(new RestServiceDef("service1") { RootUrl = InProcessWebServer.RootUrl }); + restOperationDef = ruleAppDef.DataElements.Add(new RestOperationDef("operation1") + { + RestService = restServiceDef.Name, + Verb = RestOperationVerb.Post, + UriPrototype = "api/v1/test", + BodyFormat = RestOperationBodyFormat.Json, + BodyPrototype = "{}", + Inputs = + { + new RestOperationInputParameterDef { Name = "p1", DataType = DataType.String }, + new RestOperationInputParameterDef { Name = "p2", DataType = DataType.String } + } + }); + e1Def = ruleAppDef.Entities.Add(new EntityDef("e1")); + var rs1Def = (RuleSetDef)e1Def.RuleElements.Add(new RuleSetDef("rs1") { FireMode = RuleSetFireMode.Auto, RunMode = RuleSetRunMode.SequentialRunOnce }); + rs1Def.Rules.Add(new ExecuteRestServiceActionDef("exec1") + { + Operation = restOperationDef.Name, + InputValues = + { + new ExecuteRestServiceActionParameterValueDef("p1", "\"value1\""), + new ExecuteRestServiceActionParameterValueDef("p2", "\"value2\"") + } + }); + return ruleAppDef; + } + + private static void ProcessRequest(HttpListenerContext context) + { + Console.WriteLine($"Request URI: {context.Request.Url}"); + Console.WriteLine($"Verb: {context.Request.HttpMethod}"); + Console.WriteLine("Request Headers:"); + foreach (var headerName in context.Request.Headers.AllKeys) + { + Console.WriteLine($"\t- {headerName}: {context.Request.Headers[headerName]}"); + } + + using (var response = new StreamReader(context.Request.InputStream)) + { + Console.WriteLine($"Request Body: {response.ReadToEnd()}"); + } + + var responseBuffer = Encoding.UTF8.GetBytes("{}"); + context.Response.OutputStream.Write(responseBuffer, 0, responseBuffer.Length); + Console.WriteLine(); + } + + } +} diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/Properties/AssemblyInfo.cs b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b55328f --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RuntimeOverridesViaConfig")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RuntimeOverridesViaConfig")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ad7153d5-ad79-4928-af2e-41ccad584ee5")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/RuntimeOverridesViaConfig.csproj b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/RuntimeOverridesViaConfig.csproj new file mode 100644 index 0000000..188382a --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/RuntimeOverridesViaConfig.csproj @@ -0,0 +1,85 @@ + + + + + Debug + AnyCPU + {AD7153D5-AD79-4928-AF2E-41CCAD584EE5} + Exe + RuntimeOverridesViaConfig + RuntimeOverridesViaConfig + v4.7.2 + 512 + true + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\InRule.Common.5.7.3\lib\net472\InRule.Common.dll + + + ..\packages\InRule.Repository.5.7.3\lib\net472\InRule.Repository.dll + + + ..\packages\InRule.Repository.5.7.3\lib\net472\InRule.Repository.XmlSerializers.dll + + + ..\packages\InRule.Runtime.5.7.3\lib\net472\InRule.Runtime.dll + + + ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + + + + ..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\lib\net46\System.Data.SQLite.dll + + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.8\lib\net45\System.Net.Http.Formatting.dll + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/packages.config b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/packages.config new file mode 100644 index 0000000..248c6d3 --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaConfig/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/App.config b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/App.config new file mode 100644 index 0000000..af5201a --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/App.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/InProcessWebServer.cs b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/InProcessWebServer.cs new file mode 100644 index 0000000..29fec61 --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/InProcessWebServer.cs @@ -0,0 +1,86 @@ +using System; +using System.Net; + +namespace RuntimeOverridesViaSdk +{ + public sealed class InProcessWebServer : IDisposable + { + private const int HttpPort = 9595; + + private readonly Action _processRequest; + private readonly HttpListener _httpListener; + + public InProcessWebServer(Action processRequest) + { + _processRequest = processRequest; + _httpListener = new HttpListener { AuthenticationSchemes = AuthenticationSchemes.Anonymous }; + _httpListener.Prefixes.Add(RootUrl); + _httpListener.Start(); + Result = _httpListener.BeginGetContext(WebRequestCallback, _httpListener); + } + + public static string RootUrl => $"http://localhost:{HttpPort}/"; + + public IAsyncResult Result { get; private set; } + + public HttpListenerRequest Request { get; private set; } + + public void Dispose() + { + if (_httpListener == null) return; + + lock (_httpListener) + { + try + { + ((IDisposable)_httpListener).Dispose(); + } + catch + { + } + } + } + + private void WebRequestCallback(IAsyncResult result) + { + // Avoid accessing HttpListener while/after it has been disposed + lock (_httpListener) + { + if (!_httpListener.IsListening) return; + + try + { + HttpListenerContext context = _httpListener.EndGetContext(result); + + Request = context.Request; + + try + { + if (_processRequest == null) + { + context.Response.StatusCode = (int)HttpStatusCode.OK; + context.Response.Headers.Add(HttpResponseHeader.ContentType, "text/plain"); + } + else + { + _processRequest(context); + } + } + finally + { + context.Response.OutputStream.Close(); + } + } + catch (Exception ex) + { + Console.WriteLine($"[Server] - Error: {ex.Message}"); + } + finally + { + // Set up the next context + Result = _httpListener.BeginGetContext(WebRequestCallback, _httpListener); + } + } + } + } +} diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/Program.cs b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/Program.cs new file mode 100644 index 0000000..2cb289b --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/Program.cs @@ -0,0 +1,141 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using InRule.Repository; +using InRule.Repository.EndPoints; +using InRule.Repository.RuleElements; +using InRule.Runtime; + +namespace RuntimeOverridesViaSdk +{ + internal class Program + { + static void Main(string[] args) + { + var ruleAppDef = CreateRuleApplication(out var restOperationDef, out var e1Def); + + using (new InProcessWebServer(ProcessRequest)) + { + Console.WriteLine("--- Original --------------------------------------"); + using (RuleSession session = new RuleSession(ruleAppDef)) + { + session.CreateEntity(e1Def.Name); + session.ApplyRules(); + } + + Console.WriteLine("--- Override URI Template -------------------------"); + using (RuleSession session = new RuleSession(ruleAppDef)) + { + session.Overrides.OverrideRestOperationUriTemplate(restOperationDef.Name, "api/v2/test"); + + session.CreateEntity(e1Def.Name); + session.ApplyRules(); + } + + Console.WriteLine("--- Override URI Template with parameter ----------"); + using (RuleSession session = new RuleSession(ruleAppDef)) + { + session.Overrides.OverrideRestOperationUriTemplate(restOperationDef.Name, "api/$p1$/test"); + + session.CreateEntity(e1Def.Name); + session.ApplyRules(); + } + + Console.WriteLine("--- Override Body ---------------------------------"); + using (RuleSession session = new RuleSession(ruleAppDef)) + { + session.Overrides.OverrideRestOperationBody(restOperationDef.Name, "{ \"Value\": \"Test123\" }"); + + session.CreateEntity(e1Def.Name); + session.ApplyRules(); + } + + Console.WriteLine("--- Override Body with parameter ------------------"); + using (RuleSession session = new RuleSession(ruleAppDef)) + { + session.Overrides.OverrideRestOperationBody(restOperationDef.Name, "{ \"Value\": \"$p1$\" }"); + + session.CreateEntity(e1Def.Name); + session.ApplyRules(); + } + + Console.WriteLine("--- Override Headers -----------------------------"); + using (RuleSession session = new RuleSession(ruleAppDef)) + { + session.Overrides.OverrideRestOperationHeaders(restOperationDef.Name, new [] + { + new HttpHeader("Header1", "test123"), + new HttpHeader("Header2", "test321") + }); + session.CreateEntity(e1Def.Name); + session.ApplyRules(); + } + + Console.WriteLine("--- Override Headers with parameters --------------"); + using (RuleSession session = new RuleSession(ruleAppDef)) + { + session.Overrides.OverrideRestOperationHeaders(restOperationDef.Name, new[] + { + new HttpHeader("Header1", "$p1$"), + new HttpHeader("Header2", "$p2$") + }); + session.CreateEntity(e1Def.Name); + session.ApplyRules(); + } + + } + } + + private static RuleApplicationDef CreateRuleApplication(out DataElementDef restOperationDef, out EntityDef e1Def) + { + var ruleAppDef = new RuleApplicationDef(); + var restServiceDef = ruleAppDef.EndPoints.Add(new RestServiceDef("service1") { RootUrl = InProcessWebServer.RootUrl }); + restOperationDef = ruleAppDef.DataElements.Add(new RestOperationDef("operation1") + { + RestService = restServiceDef.Name, + Verb = RestOperationVerb.Post, + UriPrototype = "api/v1/test", + BodyFormat = RestOperationBodyFormat.Json, + BodyPrototype = "{}", + Inputs = + { + new RestOperationInputParameterDef { Name = "p1", DataType = DataType.String }, + new RestOperationInputParameterDef { Name = "p2", DataType = DataType.String } + } + }); + e1Def = ruleAppDef.Entities.Add(new EntityDef("e1")); + var rs1Def = (RuleSetDef)e1Def.RuleElements.Add(new RuleSetDef("rs1") { FireMode = RuleSetFireMode.Auto, RunMode = RuleSetRunMode.SequentialRunOnce }); + rs1Def.Rules.Add(new ExecuteRestServiceActionDef("exec1") + { + Operation = restOperationDef.Name, + InputValues = + { + new ExecuteRestServiceActionParameterValueDef("p1", "\"value1\""), + new ExecuteRestServiceActionParameterValueDef("p2", "\"value2\"") + } + }); + return ruleAppDef; + } + + private static void ProcessRequest(HttpListenerContext context) + { + Console.WriteLine($"Request URI: {context.Request.Url}"); + Console.WriteLine($"Verb: {context.Request.HttpMethod}"); + Console.WriteLine("Request Headers:"); + foreach (var headerName in context.Request.Headers.AllKeys) + { + Console.WriteLine($"\t- {headerName}: {context.Request.Headers[headerName]}"); + } + + using (var response = new StreamReader(context.Request.InputStream)) + { + Console.WriteLine($"Request Body: {response.ReadToEnd()}"); + } + + var responseBuffer = Encoding.UTF8.GetBytes("{}"); + context.Response.OutputStream.Write(responseBuffer, 0, responseBuffer.Length); + Console.WriteLine(); + } + } +} diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/Properties/AssemblyInfo.cs b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7570a63 --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RuntimeOverridesViaSdk")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RuntimeOverridesViaSdk")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5e9273f5-548a-4813-9499-5201b2160060")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/RuntimeOverridesViaSdk.csproj b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/RuntimeOverridesViaSdk.csproj new file mode 100644 index 0000000..9b0fcf6 --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/RuntimeOverridesViaSdk.csproj @@ -0,0 +1,85 @@ + + + + + Debug + AnyCPU + {5E9273F5-548A-4813-9499-5201B2160060} + Exe + RuntimeOverridesViaSdk + RuntimeOverridesViaSdk + v4.7.2 + 512 + true + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\InRule.Common.5.7.3\lib\net472\InRule.Common.dll + + + ..\packages\InRule.Repository.5.7.3\lib\net472\InRule.Repository.dll + + + ..\packages\InRule.Repository.5.7.3\lib\net472\InRule.Repository.XmlSerializers.dll + + + ..\packages\InRule.Runtime.5.7.3\lib\net472\InRule.Runtime.dll + + + ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + + + + ..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\lib\net46\System.Data.SQLite.dll + + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.8\lib\net45\System.Net.Http.Formatting.dll + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/packages.config b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/packages.config new file mode 100644 index 0000000..248c6d3 --- /dev/null +++ b/Developer Samples/RuntimeOverrides/RuntimeOverridesViaSdk/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index e73ff92..c11f686 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ If you would like to request additional samples from InRule Technology, please w | OAuth Token Sample | Authoring Samples | Functional Samples\OAuthTokenSample | | Promote Rule App between Catalogs using Command Line | Developer Samples | CommandLineTools\PromoteRuleApp | | Query value list | Authoring Samples | Chicago Food Tax Generator | -| Windows Container Samples | Developer Samples | WindowsContainers +| Runtime Overrides | Developer Samples | RuntimeOverrides | | Salesforce | Developer Samples | SalesforceSamples | | String operations | Authoring Samples | String Matching | | Unbound entities | Developer Samples | AddCollectionMembers
CreateEntityFromXml
CreateRuleSession-Catalog
CreateRuleSession-FileSystem
CreateRuleSession-InMemory
DynamicValueAccess
GetChangedValues
GetEntityXml
LaunchIrVerify
RulesInCode |