Calling the Rules Engine as a Service

  • Updated

This article contains the following sections:

Synchronously calling the REST Service

The following example demonstrates calling the irServer - Rule Execution Service REST interface synchronously with the legacy WebRequest class.


 // The name of the ruleApp in the Catalog
string ruleApp = "MortgageCalculator";

// The address of the Rule Execution Service
string ruleExecutionServiceURI = "http://localhost/InRuleRuleEngineService_v5.0.16/HttpService.svc";

// The name of the Entity
string entityName = "Mortgage";// The name of the RuleSet to execute, or use 'ApplyRules' if found to be null.
string ruleSetName = "PaymentSummaryRules";

// The entity state as a C# dynamic type
dynamic entityState = new
{
 LoanInfo = new
  {
Principal = 53000m, APR = 7.625f, TermInYears = 15
  }
};
// We use Newtonsoft's Json.Net library to convert this dynamic C# object to a JSON string
string entityStateJsonInput = JsonConvert.SerializeObject(entityState);

// New create the full request, inserting the JSON string that represents EntityState.
dynamic requestData = new
{
RuleApp = new
{
RepositoryRuleAppRevisionSpec = new
       {
RuleApplicationName = ruleApp
       }
   },
EntityName = entityName,
EntityState = entityStateJsonInput,
RuleSetName = ruleSetName
};
string requestDataString = JsonConvert.SerializeObject(requestData);
//If no ruleSetName exists, execute Auto rules, otherwise execute explicit rule.
string postUri;
if (string.IsNullOrEmpty(ruleSetName))
{ postUri = ruleExecutionServiceURI + "/ApplyRules"; }
else
{ postUri = ruleExecutionServiceURI + "/ExecuteRuleSet"; }

// Encode our string into an array of bytes, needed by WebRequest.
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(requestDataString);

// Create and prepare the request
WebRequest webRequest = WebRequest.Create(postUri);

// ApplyRules only works as a POST, not a GET
webRequest.Method = "POST";

// Our EntityState is encoded as an JSON document, not XML.
webRequest.ContentType = "application/json";

// WebRequest is old, and can't count by itself.
webRequest.ContentLength = bytes.Length;

string httpResponse;

// Create our requestStream by opening the request, make sure it gets disposed when done.
using (var requestStream = webRequest.GetRequestStream())
{
// send the data
requestStream.Write(bytes, 0, bytes.Length);
}
// In case it has not already been mentioned this is a rather primitive way of
// making an HTTP based request.  We recommend you read the HttpClient based code samples
// elsewhere in this document, as that Asynchronous approach is a better way to go.
try
{
HttpWebResponse response = webRequest.GetResponse() as HttpWebResponse;
using (var stream = response.GetResponseStream())
{
var reader = new StreamReader(stream, Encoding.UTF8);
httpResponse = reader.ReadToEnd();
  }
}
catch (WebException ex)
{
using (var stream = ex.Response.GetResponseStream())
{
var reader = new StreamReader(stream, Encoding.UTF8);
httpResponse = reader.ReadToEnd();
throw new Exception(httpResponse, ex);
}
}
dynamic resultJson = JsonConvert.DeserializeObject<dynamic>(httpResponse);
string entityJsonString = resultJson.EntityState;
dynamic entityJson = JsonConvert.DeserializeObject<dynamic>(entityJsonString);
string paymentSummaryJsonString = JsonConvert.SerializeObject(entityJson.PaymentSummary);

Asynchronously calling the REST Service with JSON

The following example demonstrates calling the irServer - Rule Execution Service REST interface with a JSON based Entity State.


static void Main(string[] args)
{
  // The name of the ruleApp in the Catalog
  string ruleApp = "MortgageCalculator";

  // The address of the Rule Execution Service
  string ruleExecutionServiceURI = "http://localhost/InRuleRuleEngineService_v5.0.16/HttpService.svc";

  // The name of the Entity
  string entityName = "Mortgage";

  // The name of the RuleSet to execute, or use 'ApplyRules' if found to be null.
  string ruleSetName = "PaymentSummaryRules";

  // The entity state as a C# dynamic type
  dynamic entityState = new

  {
      LoanInfo = new
      {
          Principal = 53000m, APR = 7.625f, TermInYears = 15
      }
  };
  // A console application's main() entry point cannot be declared as async, so here
  // we are creating an Async task to execute the Async method, then we will wait on
  // the result.
  Task<string> httpTask = AsyncRestJsonCatalog(ruleExecutionServiceURI, ruleApp,
                                entityName, entityState, ruleSetName);

  // Calling the Result property of a Task object will block this thread until
  // the Task has had a chance to complete in it's worker thread.
  string httpTaskResult = httpTask.Result;

  // After this call you can inspect the raw result (as JSON) in resultJson, but note
  // that the EntityState will be serialized Json and must be decoded.
  dynamic resultJson = JsonConvert.DeserializeObject<dynamic>(httpTaskResult);
  string entityJsonString = resultJson.EntityState;

  // Decode the serialized entity Json into a dynamic entity.
  dynamic entity = JsonConvert.DeserializeObject<dynamic>(entityJsonString);
}
private async static Task<string> AsyncRestJsonCatalog(string ruleExecutionServiceURI, string ruleApp,
                  string ruleApplicationEntityName, dynamic entityStateObjectInput, string ruleSetName)
{
  // We use Newtonsoft's Json.Net library to convert this dynamic C# object to a JSON string
  string entityStateJsonInput = JsonConvert.SerializeObject(entityStateObjectInput);
  // New create the full request, inserting the JSON string that represents EntityState.
  dynamic requestData = new
  {
      RuleApp = new
      {
          RepositoryRuleAppRevisionSpec = new
          {
              RuleApplicationName = ruleApp
          }
      },
      EntityName = ruleApplicationEntityName,
      EntityState = entityStateJsonInput,
      RuleSetName = ruleSetName
  };
  string requestDataString = JsonConvert.SerializeObject(requestData);

  //If no ruleSetName exists, execute Auto rules, otherwise execute explicit rule.
  string postUri;
  if (string.IsNullOrEmpty(ruleSetName))
  { postUri = ruleExecutionServiceURI + "/ApplyRules"; }
  else
  { postUri = ruleExecutionServiceURI + "/ExecuteRuleSet"; }

  // Our EntityState is encoded as JSON document, not XML.
  string mediaType = "application/json";

  // Async call to HttpClient with an HttpContent and wait for result.
  HttpContent content = new StringContent(requestDataString, Encoding.UTF8, mediaType);
  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.PostAsync(postUri, content);

  // Async convert the HttpResponseMessage's content to a string.
  string responsestring = await response.Content.ReadAsStringAsync();

  // We're done, return result.
  return responsestring;
}

Asynchronously calling the REST Service with XML

The following example demonstrates calling the irServer - Rule Execution Service REST interface with an XML based Entity State.


static void Main(string[] args)
{
  // The name of the ruleApp in the Catalog
string ruleApp = "MortgageCalculator";
// The address of the Rule Execution Service
string ruleExecutionServiceURI = "http://localhost/InRuleRuleEngineService/HttpService.svc";
// The Entity Name:
string entityName = "Mortgage";
// The name of the RuleSet to execute, or use 'ApplyRules' if found to be null.
string ruleSetName = "PaymentSummaryRules";
// The Entity State as XML text.
string entityStateXMLInput = @"<?xml version='1.0' encoding='utf-8'?>
<Mortgage xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
  <LoanInfo>
      <Principal>53000</Principal>
      <APR>7.625</APR>
      <TermInYears>15</TermInYears>
  </LoanInfo>
  <PaymentSummary/>
</Mortgage>";

// A console application's main() entry point cannot be declared as async, so here
// we are creating an Async task to execute the Async method, then we will wait on
// the result.
Task<string> httpTask = AsyncRestXmlCatalog(ruleExecutionServiceURI, ruleApp, entityName,
entityStateXMLInput, ruleSetName);


// Calling the Result property of a Task object will block this thread until
// the Task has had a chance to complete in it's worker thread.

string httpTaskResult = httpTask.Result;

Console.WriteLine(httpTaskResult);

// Now let's extract the <EntityState> element, which has been encoded.
// The Value property of the XElement will automatically decode the contents
// and expose it as a string, which lets us look at the inner XML document "EntityState".
// It's worth observing that while the input was encoded as UTF-8, this result is in
// UTF-16.
XDocument xmldoc = XDocument.Parse(httpTaskResult);
string xmlEntityStateOutput =
     (from n in xmldoc.Descendants()
      where n.Name.LocalName == "EntityState"
      select n.Value).FirstOrDefault();

// Wonderful!  Now lets take that concept further and extract just the
// <PaymentSummary> node from the document, which gives us our computed "answers".
XDocument xmlentitystatedoc = XDocument.Parse(xmlEntityStateOutput);
  string paymentSummaryXml = (from n in xmlentitystatedoc.Descendants()
                            where n.Name.LocalName == "PaymentSummary"
                            select n.ToString()).FirstOrDefault();
 }
private async static Task<string> AsyncRestXmlCatalog(string ruleExecutionServiceURI,
                                                      string ruleApp,
                                                      string entityName,
                                                      string entityStateXMLInput,
                                                      string ruleSetName)
{
// We must encode the Entity State XML into a valid XML string so that
// it can be wrapped with the outer XML request document.
string entityStateXMLEncoded = SecurityElement.Escape(entityStateXMLInput);
string rootNodeName;
if (string.IsNullOrEmpty(ruleSetName))
 { rootNodeName = "ApplyRulesRequest"; }
else
 { rootNodeName = "ExecuteRuleSetRequest"; }

// Now we generate the outer XML request document.
string requestXML = $@"<?xml version='1.0' encoding='utf-8'?>
<{rootNodeName} xmlns='http://www.inrule.com/XmlSchema/Schema'>
  <RuleApp>
      <RepositoryRuleAppRevisionSpec>
          <RuleApplicationName>{ruleApp}</RuleApplicationName>
      </RepositoryRuleAppRevisionSpec>
  </RuleApp>
  <EntityState>{entityStateXMLEncoded}</EntityState>
  <EntityName>{entityName}</EntityName>
  <RuleSetName>{ruleSetName}</RuleSetName>
</{rootNodeName}>";
//If no ruleSetName exists, execute Auto rules, otherwise execute explicit rule.
string postUri;
if (string.IsNullOrEmpty(ruleSetName))
 { postUri = ruleExecutionServiceURI + "/ApplyRules"; }
else
 { postUri = ruleExecutionServiceURI + "/ExecuteRuleSet"; }

// Our EntityState is encoded as an XML document, not JSON.
string mediaType = "application/xml";

// Async call to HttpClient with an HttpContent and wait for result.
HttpContent content = new StringContent(requestXML, Encoding.UTF8, mediaType);
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(postUri, content);

// Async convert the HttpResponseMessage's content to a string.
string responseXML = await response.Content.ReadAsStringAsync();

// We're done, return result.
return responseXML;

Calling the SOAP EndPoint using a Service Reference

Prerequisites A valid Service Reference

The following sample represents how to call irServer Rule Execution Service SOAP EndPoint using a service reference:


using (RuleEngineServiceClient proxy = new RuleEngineServiceClient())
{
 try
 {
         // Get RuleApp as defined in the config (RepositoryRuleApp or FileSystemRuleApp)
         RepositoryRuleApp rules = new RepositoryRuleApp();
         rules.RepositoryServiceUri = "http://server/InRuleCatalogService/Service.svc";
         RepositoryRuleAppRevisionSpec spec = new RepositoryRuleAppRevisionSpec();
         spec.RuleApplicationName = "MortgageCalculator";
         rules.RepositoryRuleAppRevisionSpec = spec;
         rules.UserName = "Admin";
         rules.Password = "password";

         // Create new ApplyRulesRequest
         ApplyRulesRequest request = new ApplyRulesRequest();
         request.RuleApp = rules;
         request.EntityName = "Mortgage";
         request.RuleEngineServiceOutputTypes = new RuleEngineServiceOutputTypes();
         request.RuleEngineServiceOutputTypes.ActiveNotifications = true;
         request.RuleEngineServiceOutputTypes.ActiveValidations = true;
         request.RuleEngineServiceOutputTypes.EntityState = true

         // Load state XML
         Console.WriteLine("- Loading XML state for 'Invoice'...");
         request.EntityState =
"<Mortgage><LoanInfo><Principal>500000</Principal><APR>6.875</APR
< TermInYears > 30 </TermInYears ></LoanInfo ><PaymentSummary/ ></Mortgage > "
;
         Console.WriteLine("Input State:");
         Console.WriteLine(request.EntityState);
         Console.WriteLine("");

         // Submit Request
         Console.WriteLine("- Calling ApplyRules() from RuleEngineService...");
         RuleEngineServiceResponse response = proxy.ExecuteRuleEngineRequest(request)

         Console.WriteLine("Active Notifications:");
         foreach (Notification notification in response.ActiveNotifications)
         {
                 Console.WriteLine(notification.NotificationType + ": " + notification.Message);
         }
         Console.WriteLine("");
         
Console.WriteLine("Active Validations:");
         foreach (Validation validation in response.ActiveValidations)
         {
                 Console.WriteLine(validation.InvalidMessageText);
         }
         Console.WriteLine("");
         Console.WriteLine("Output State:");
         // Note: XML formatting not maintained in response
         Console.WriteLine(response.EntityState);
         Console.WriteLine("");
 }
 catch (Exception ex)
 {
         Console.WriteLine("Unknown exception occurred during RuleEngineService request: " +
ex.ToString());
 }
}
Console.WriteLine("[END ServiceReferenceConsumer Sample]")

For more information, see the article: irServer - Rule Execution Service

Was this article helpful?

0 out of 0 found this helpful

Comments

0 comments

Please sign in to leave a comment.