Notify client from the server
In most cases, when we perform server-side processing, a request is sent and a response is expected directly.
But sometimes we don't want to wait for the result of a server-side processing.
This is why it is possible to notify the client from the server.
How it works
Behind the scenes, SignalR is used. It is a library maintened by Microsoft which allows server code to send asynchronous notifications to client-side web applications.
In this guide, we will see how to create our first notification.
Define a notification
First of all, each notification must be declared. By using Neos Studio, you can define it.
A notification is in a module and must have a unique name. There can't be two notifications in the same cluster with the same name.
It is possible to define the .NET type of the argument that will be passed from server to client. This can be a simple type or a DataObject type. In case the type is not filled in, no argument will be expected.
Let's take the following notification as an example :
Module name = Whatever
Name = FirstNotification
Arguments .NET type = Northwind.Application.Abstractions.DataObjects.FirstNotificatioArgs
At the same time, create a data object FirstNotificationArgs with a single string property Message that will match the type of the argument.
After creating the notification, generate the application.
Send a notification from the server
In the code of a server method or an event rule of an entity view, you can send a notification.
To do this, you need to get the INotificationRegistry interface through the GetService method or in case the code is written in a Business Assembly, through the constructor.
Here, we will use the GetService method.
INotificationRegistry notificationRegistry = GetService<INotificationRegistry>();
The INotificationRegistry interface has a property for each defined notification. So we find our FirstNotification property corresponding to the notification created previously.
This property provides two methods : SendToCurrentConnectionAsync and SendToAllConnectionsAsync.
Send a notification to the current connection
By using the SendToCurrentConnectionAsync method, the notification will be send only to the connection that executed the request to the server.
To understand the method, let's take an example. Let's say we have :
- A notification without argument.
- A server method which use the
SendToCurrentConnectionAsyncmethod. - An action in a UI view which call the server method.
- An handler that display a message to the user when the notification is sent from the server.
The user opens two browser tabs on the same UI view :
- In the first tab, the user click on the action, the server method is executed, the notification is sent, the message is displayed.
- In the second tab, nothing happened.
Send a notification to all connections
By using the SendToAllConnectionsAsync method, the notification will be send to all active connections.
Let's go back to the previous example and replace the SendToCurrentConnectionAsync method with the SendToAllConnectionsAsync method :
- In the first tab, the user click on the action, the server method is executed, the notification is sent, the message is displayed.
- In the second tab, the message is also displayed.
So, to send a notification from the server, you only need the following code :
FirstNotificationArgs args = new FirstNotificationArgs()
{
Message = "Notification message"
};
INotificationRegistry notificationRegistry = GetService<INotificationRegistry>();
await notificationRegistry.FirstNotification.SendToAllConnectionsAsync(args);
Execute client-side code when a notification is received
Now, on the client side, we have to execute some code when we receive a notification.
In the view code, the Notifications property of INotifications type is accessible and as on the server side, the interface has a property for each defined notification.
To add a handler to a notification, use the AddHandler method like this :
Notifications.FirstNotification.AddHandler(Methods.HandleFirstNotification);
Where the method HandleFirstNotification has a args parameter of type Northwind.Application.Abstractions.DataObjects.FirstNotificationArgs.
It is also possible to add a handler with a lambda expression like this :
Notifications.FirstNotification.AddHandler(async (args) =>
{
// UIResources.Core.FirstNotificationTitle (Scope=Frontend) => "First notification"
await ShowMessageAsync(MessageType.Positive, UIResources.Core.FirstNotificationTitle, args.Message);
});
When the UI view is closed, all the handlers are removed. But it is still possible to delete a handler manually like this :
Notifications.FirstNotification.RemoveHandler(Methods.HandleFirstNotification);
Invoke client-side code from the server
It is also possible to invoke client-side code from the server by using the InvokeCurrentConnectionAsync method. You can use it to invoke the client for the current connection.
The client must return a synchronous response to the notification by returning a value of the type expected by the function linked to AddHandler.
- Define a notification in Neos Studio,
Notification name: MyClientAction
Arguments .Net data type: string
Response .NET data type: bool
- Server side : Invoke the client for the current connection.
bool response = await _notificationRegistry.MyClientAction.InvokeCurrentConnectionAsync<bool>(args);
- Client side : Add a handler to the notification.
Notifications.MyClientAction.AddHandler(m => Method.MyAction(m));
The method MyAction method must return a bool value.