This page covers setting up IceLib custom handler and inter-application notifications via CustomNotification and some of its associated classes (CustomResponse, CustomRequest, CustomMessage, CustomMessageHeader, CustomMessageType, and CustomNotificationReceived). All of these classes are contained in the ININ.IceLib.Connection.Extensions namespace.
General Concepts
This section contains the following subsections.
Overview
The CustomNotification class allows initiation of custom handlers via SendServerRequestNoResponse (or SendServerRequestNoResponseAsync) and inter-application notifications via SendApplicationRequest (or SendApplicationRequestAsync) and SendApplicationResponse (or SendApplicationResponseAsync). The CustomNotification class also allows for reception of notifications from either custom handlers or other applications via the CustomNotificationReceived event. The request and response functions utilize the CustomRequest and CustomResponse classes respectively to send notifications. The CustomRequest and CustomResponse classes both rely on the CustomMessage class to send custom notifications. Likewise the CustomNotificationReceived event passes a parameter of the type CustomNotificationReceivedEventArgs which relies on the CustomMessage class to receive custom message notifications.
Back to IntroductionAbout Custom Messages
The CustomMessage class, the data transfer container for all CustomNotifications, is uniquely identified by its CustomMessageHeader. A CustomMessageHeader, and hence a CustomMessage, is uniquely identified by its four components the CustomMessageType, ObjectType, ObjectId, and EventId. Applications will have to know what type(s) of CustomMessages they will receive, and start watching accordingly. Applications start watches, via StartWatching or StartWatchingAsync for messages uniquely identified by a CustomMessageHeader. When the CustomMessageHeader(s) are matched the CustomNotificationReceived event, which should be hooked prior to any start watch calls, will be invoked.
CustomMessageType is the first part of identification of a CustomMessageHeader. It represents the message type and can have the values ServerNotification, ApplicationRequest or ApplicationResponse. ServerNotification is the notification type that an application will send to or receive from a custom handler. Notifications are sent to a custom handler via the SendServerRequestNoResponse or SendServerRequestNoResponseAsync methods. ApplicationRequest is the notification type that an application will receive when another application sends out notification via the SendApplicationRequest or SendApplicationRequestAsync methods. ApplicationResponse is the notification type that an application will receive when another application responds to an ApplicationRequest via the SendApplicationResponse or SendApplicationResponseAsync methods.
ObjectType is the second part of identification of a CustomMessageHeader. This represents the class of message and will always be a String with the value "Custom" for all CustomNotifications.
ObjectId is the third part of identification of a CustomMessageHeader and can be any user determined string.
EventId is the fourth part of identification of a CustomMessageHeader and can be any user determined string.
Custom Handler Notifications
This section contains the following subsections.
Custom Handlers - Background
When it is desirable IC Server's functionality may be extended via custom handlers, which are developed using Interaction Designer. Interaction Designer is IC's graphical programming and application generator tool.
All custom handlers always start with an initiator as their first step and an initiator is comprised of a set of events that start a custom handler. Custom handlers are registered with Interaction Processor, which watches for matching initiator events and launches the proper custom handler when an when a match is found. "Custom Notification", is one of the available Initiators when changing a custom handlers initiator and triggers on notifications sent via the SendServerRequestNoResponse or SendServerRequestNoResponseAsync methods. Additionally during a custom handlers execution it can send a custom notification as one of its steps. This custom notification can be picked up with the CustomNotificationReceived event assuming the event is hooked and the appropriate StartWatching or StartWatchingAsync call was made.
A CustomNotification initiator can be initiated via IceLib by sending a CustomRequest via SendServerRequestNoResponse or SendServerRequestNoResponseAsync. See the following section Generating a Custom Handler Notification for more information on building a notification for a custom handler.
Back to IntroductionGenerating a Custom Handler Notification
Initiating a custom handler is possible through the SendServerRequestNoResponse or SendServerRequestNoResponseAsync methods. StartWatching or StartWatchingAsync can be used along with the CustomNotificationReceived event to receive notifications from a custom handler when it sends out a custom notification.
Note |
---|
Custom handlers only support an array of strings as message data. Ensure that any CustomRequests sent via SendServerRequestNoResponse or SendServerRequestNoResponseAsync only contain an array of strings by only utilizing the CustomRequest..::..Write(String []) method. Also any CustomMessages received via the CustomNotificationReceived event with the CustomMessageType of ServerNotification are only read from with the ReadStrings method. |
Custom Handler Example
In this example the CreditCardSwipeCustomNotification class takes care of processing a credit card swipe and sending the proper information off to a custom handler installed on the IC Server. The custom handler would process the custom notification's ITEMCODE to determine a price and would then send a custom notification. The class CrediCardSwipedCompletePurchase would receive the custom handler's custom notification and process the information sent along to actually complete the purchase.
class CreditCardSwipeCustomNotification
{
private CustomNotification _customNotification;
public CreditCardSwipeCustomNotification(Session session)
{
_customNotification = new CustomNotification(session);
}
public void SendCreditCardSwipe()
{
//Load a string array with the message
String[] purchaseInfo = new string[]
{
"Master Card",
"1234 5678 9876 5432",
"01/2014",
"965",
"ITEMCODE:12345" //An item code that will be used to look-up price
};
//Create a custom request, the targeted custom handler should be watching for object ID "SwipeObjectID"
// and notification event (event ID) "SwipeEventID". Both of these strings would be entered into the
// custom notification initiator of the custom handler. NOTE: both strings would be entered without
// quotes.
CustomRequest creditCardSwipeNotification = new CustomRequest(
new CustomMessageHeader(CustomMessageType.ServerNotification, "SwipeObjectID", "SwipeEventID"));
//Load the request with data
creditCardSwipeNotification.Write(purchaseInfo);
//Send the notification to the custom handler
_customNotification.SendServerRequestNoResponse(creditCardSwipeNotification);
}
}
class CrediCardSwipedCompletePurchase : CustomNotification
{
public CrediCardSwipedCompletePurchase(Session session)
: base(session)
{
CustomNotificationReceived += HandleCompletePurchaseCustomNotification;
//The custom handler would send a custom notification with
// a Custom Object Identifier of "CompletePurchaseObjectID and
// a Custom Event Identifier of "CompletePurchaseEventID".
CustomMessageHeader customHandlerMessageHeader = new CustomMessageHeader(
CustomMessageType.ServerNotification, "CompletePurchaseObjectID", "CompletePurchaseEventID");
StartWatching(new[] { customHandlerMessageHeader });
}
private void HandleCompletePurchaseCustomNotification(object sender, CustomNotificationReceivedEventArgs e)
{
var infoForPurchase = e.Message.ReadStrings();
if (infoForPurchase != null && infoForPurchase.Length > 4)
{
var creditCardType = infoForPurchase[0];
var creditCardNumner = infoForPurchase[1];
var creditCardExpirationDate = infoForPurchase[2];
var creditCardCSV = infoForPurchase[3];
var itemPrice = infoForPurchase[4];
MakePurchase(creditCardType, creditCardNumner, creditCardExpirationDate, creditCardCSV, itemPrice);
}
}
}
Inter-Application Notifications
This section contains the following subsections.
- Application Requests and Application Responses
- Application to Application Custom Notification Example
Application Requests and Application Responses
The SendApplicationRequest and SendApplicationRequestAsync methods can be used to send out requests to other logged in IceLib applications. An IceLib application can listen for application requests by using StartWatching or StartWatchingAsync and respond by using SendApplicationResponse or SendApplicationResponseAsync.
Back to IntroductionApplication to Application Custom Notification Example
Application Custom Notifications:
Application A wants to send out a custom notification with ObjectId "AppAObjectId" and EventId "AppAEventId" to to a custom handler that application B watches for. Application B sends back a custom notification with an array of strings containing "Foo" and "Bar".
In order for application B to receive this custom notification, first it would setup an event handler to listen for the CustomNotificationReceived event and then it would StartWatching or StartWatchingAsync on a CustomMessageHeader with CustomMessageType of ApplicationRequest, ObjectId "AppAObjectId" and EventId "AppAEventId". Notice that the handler HandleApplicationACustomNotification creates a CustomResponse object with the received message. SendApplicationResponse modifies the CustomMessageType to be ApplicationResponse and utilizes the ObjectId and EventId from the passed in message.
class ApplicationBCustomNotification : CustomNotification
{
public ApplicationBCustomNotification(Session session)
: base(session)
{
CustomNotificationReceived += HandleApplicationACustomNotification;
CustomMessageHeader applicationAMessageHeader = new CustomMessageHeader(
CustomMessageType.ApplicationRequest, "AppAObjectId", "AppAEventId");
StartWatching(new[] { applicationAMessageHeader });
}
private void HandleApplicationACustomNotification(object sender, CustomNotificationReceivedEventArgs e)
{
//Create a custom response
CustomResponse applicationBResponse = new CustomResponse(e.Message);
//Load a string array with the message
String[] message = new string[]
{
"Foo",
"Bar",
};
//Load the message into the custom request
applicationBResponse.Write(message);
//Send the message to application A
SendApplicationResponse(applicationBResponse);
}
}
In order for the application A to receive the custom notification that application B is responding with, first it would setup an event handler to listen for the CustomNotificationReceived event and then it would StartWatching or StartWatchingAsync, on a CustomMessageHeader with CustomMessageType of ApplicationResponse, ObjectId "AppAObjectId" and EventId "AppAEventId". Notice that the ObjectId and the EventId are the same as those sent with the request; this is because by convention a SendApplicationResponse is created with the original message.
To start triggering the request notifications from application A to application B and the response back, application A would call SendApplicationRequest() from the snippet below.
class ApplicationACustomNotification : CustomNotification
{
public ApplicationACustomNotification(Session session)
: base(session)
{
CustomNotificationReceived += HandleApplicationBCustomNotification;
CustomMessageHeader applicationBMessageHeader = new CustomMessageHeader(
CustomMessageType.ApplicationResponse, "AppAObjectId", "AppAEventId");
StartWatching(new[] { applicationBMessageHeader });
}
private void HandleApplicationBCustomNotification(object sender, CustomNotificationReceivedEventArgs e)
{
//Application B response received perform an action
try
{
//Attempt to read the strings sent from application B
string[] message = e.Message.ReadStrings();
if (message.Contains("Foo") && message.Contains("Bar") && message.Length == 2)
{
Console.WriteLine("Application B responded with the expected strings: {0}",
String.Join(",", message));
}
else
{
Console.WriteLine("Application B responded, but not with the expected strings: {0}",
String.Join(",", message));
}
}
catch (ININ.IceLib.IceLibException)
{
Console.WriteLine("Application B responded, but did not include any strings.");
}
}
public void SendApplicationRequest()
{
//Create a custom request
CustomRequest applicationARequest = new CustomRequest(
new CustomMessageHeader(CustomMessageType.ApplicationRequest, "AppAObjectId", "AppAEventId"));
//Send the notification to application B
SendApplicationRequest(applicationARequest);
}
}