Implement In-App Notifications with JavaScript in Dynamics 365

Introduction

Wouldn't it be nice if next time you logged into Dynamics you were immediately notified of all the important events that happened while you were gone? Leads assigned to you, opportunities your team closed, cases opened? This is all now possible with 'in-app notifications' for Dynamics 365.

Enable the feature within your model-driven apps and users will see notifications when they log in, navigate pages, or are on a page for more than a minute.

You can register a notification from the front-end, back-end, or over the REST API.

Enable the feature

  1. Navigate to the maker admin(https://make.powerapps.com/), open the model-driven app you would like to enable this feature in, and select the edit.
  2. Select settings, Navigate to Features, and enable 'In-app notifications'.
    Setting Features

After refreshing your browser you should see the notification bell in your header.

Notifications

Examples of in-app notifications

Certainly! Here is an illustrative example: when the case is assigned to another user, a notification will be displayed for the assigned user.

Create/update the web Resource

Create/update the web Resource and add the below code on the “onchange” event of the owner filed.

function displayInAppNotification(executionContext) {
    var formContext = executionContext.getFormContext();
    
    var OwnerId = formContext.getAttribute("ownerid").getValue();

    // Getting the GUID of the lookup record
    var Id = OwnerId[0].id;
    var caseNumber = formContext.getAttribute("ticketnumber").getValue();
    var CaseId = formContext.data.entity.getId();

    var userId = Id.replace(/{|}/g, '');
    var systemuserid = userId;

    var notificationRecord = {
        "title": "Case has been assigned to you",
        "body": "Case has been assigned to you Case Number: " + caseNumber + "",
        "[email protected]": "/systemusers(" + systemuserid + ")",
        "icontype": 100000000 // info 
    };

    // Create notification record
    Xrm.WebApi.createRecord("appnotification", notificationRecord)
        .then(
            function success(result) {
                console.log("notification created with ID: " + result.id);
            },
            function (error) {
                console.log(error.message);
            }
        );
}

Alternatively, we can achieve the same functionality with the following code.

function displayInAppNotification(executionContext) {
    var formContext = executionContext.getFormContext();
    
    var OwnerId = formContext.getAttribute("ownerid").getValue();

    // Getting the GUID of the lookup record
    var Id = OwnerId[0].id;
    var caseNumber = formContext.getAttribute("ticketnumber").getValue();
    var CaseId = formContext.data.entity.getId();
    var CaseGuid = CaseId.replace(/{|}/g, '');

    var userId = Id.replace(/{|}/g, '');
    var systemuserid = userId;

    var notificationEtn = {
        title: 'Case Has been assigned to you',
        body: 'Case has been assigned to you Case Number: ' + caseNumber + '',
        '[email protected]': '/systemusers(' + systemuserid + ')',
        icontype: 100000000,
        toasttype: 200000000 
    };

    Xrm.WebApi.createRecord('appnotification', notificationEtn)
        .then((result) => {
            console.log('notification registered with ID: ' + result.id);
        })
        .catch((ex) => console.error(`error message: ${ex.message}`));
}

Library new case

Handler properties

After adding the event, save and publish. Subsequently, I am attempting to assign the owner for the case record below.

Test-1

Test-1 details

After assigning the case, the following notification is received.

Notifications

Case assigned to you

The following example shows how to create a notification with a single URL action.

function displayInAppNotification(executionContext) {
    var formContext = executionContext.getFormContext();
    
    var OwnerId = formContext.getAttribute("ownerid").getValue();

    // Getting the GUID of the lookup record
    var Id = OwnerId[0].id;
    var caseNumber = formContext.getAttribute("ticketnumber").getValue();
    var CaseId = formContext.data.entity.getId();
    var CaseGuid = CaseId.replace(/{|}/g, '');

    var userId = Id.replace(/{|}/g, '');
    var systemuserid = userId;

    var notificationEtn = {
        title: 'Case Has been assigned to you',
        body: 'Case has been assigned to you Case Number: ' + caseNumber + '',
        '[email protected]': '/systemusers(' + systemuserid + ')',
        icontype: 100000000,
        toasttype: 200000000,
        data: JSON.stringify({
            actions: [{
                title: 'Open Case',
                data: {
                    url: '?pagetype=entityrecord&etn=incident&id=' + CaseGuid + '',
                    navigationTarget: 'dialog',
                },
            }],
        }),
    };

    Xrm.WebApi.createRecord('appnotification', notificationEtn)
        .then((result) => {
            console.log('notification registered with ID: ' + result.id);
        })
        .catch((ex) => console.error(`error message: ${ex.message}`));
}

After the case is assigned, a notification is received along with an action. Clicking on 'Open Case' will open the popup case record.

Open case

After clicking the 'Open case' action, the case record will be displayed in a popup window.

Demo testing

Changing the notification icon

There is support for different types of notifications - errors, information, mentions, failures, warnings, etc.

Icon Type Value
Info 100000000
Success 100000001
Failure 100000002
Warning 100000003
Mention 100000004

As you saw in the GIF, there is support for links but also a variety of ways to open them. Dialogs, inline, or new windows are all supported.

Storage

Before you get crazy with the notifications just be aware these notifications are all stored in a table in your database therefore you are paying database storage prices for the data. You can add a ttlinseconds property to the notificationEtn above to force expiry after a certain period of time. The default is 1,209,600 seconds (2 weeks).

Once an individual notification is dismissed (X is clicked) it is removed from the table, however, selecting 'dismiss all' from the notification pane DOES NOT remove rows from the table.

Managing security for notifications

The in-app notification feature uses three tables. A user needs to have the correct security roles to receive notifications and to send notifications to themselves or other users.

In addition to the appropriate table permissions, a user must be assigned the Send In-App Notification prvSendAppNotification the privilege to execute the SendAppNotification message. The privilege is granted to the Environment Maker role by default. This privilege is required for sending in-app notifications. It isn't required to receive notifications.

Usage Required table privileges
The user has no in-app notification bell and receives no in-app notification None: Read privilege on the app notification table.
Users can receive in-app notifications Basic: Read privilege on the app notification table.

Create, Read, Write, and Append privileges on the model-driven app user setting.

Read and AppendTo privileges on setting definition.
Users can send in-app notifications to self Basic: Create and Read privileges on the app notification table, and Send In-App Notification privileges.
Users can send in-app notifications to others Read privilege with Local, Deep, or Global access level on the app notification table based on the receiving user's business unit, and Send In-App Notification privilege.
Users can delete in-app notifications Global: Delete privileges on the app notification table.

Final thoughts

This feature looks amazing. It is going to be a huge value creator and was super easy to set up. Would love to hear your feedback in the comments below!


Similar Articles