|
| 1 | +# Enterprise Notifications Configuration |
| 2 | + |
| 3 | +Follow the steps below to configure the Enterprise Notifications sample introduced [here](./readme.md) |
| 4 | +## Prerequisites |
| 5 | + |
| 6 | +1. A deployed Virtual Assistant. Follow the [Create your Virtual Assistant tutorial](https://github.com/microsoft/botframework-solutions/tree/master/docs#tutorials) to complete this step which will create the core Azure services required. You can use this [sample project](/samples/EnterpriseNotification/VirtualAssistant) if preferred which has the extensions applied for you, otherwise the steps are included below. |
| 7 | + |
| 8 | +2. In addition to the core Virtual Assistant Azure services, you'll need to manually create the following Azure services: |
| 9 | + |
| 10 | + - [Azure Event Hub](https://azure.microsoft.com/en-us/services/event-hubs/) - Create [Here](https://ms.portal.azure.com/#create/Microsoft.EventHub) |
| 11 | + - [Azure Function](https://azure.microsoft.com/en-us/services/functions/) - Create [Here](https://ms.portal.azure.com/#create/Microsoft.FunctionApp) |
| 12 | + - [Azure Notification Hub](https://azure.microsoft.com/en-us/services/notification-hubs/) - Create [Here](https://ms.portal.azure.com/#create/Microsoft.NotificationHub) |
| 13 | + - [Azure Cosmos DB](https://azure.microsoft.com/en-us/services/cosmos-db/) - Create [Here]() |
| 14 | + |
| 15 | +## Event Producer |
| 16 | + |
| 17 | +This sample includes an example [Event Producer](/samples/EnterpriseNotification/EventProducer) console application that sends an Event to the Event Hub for processing simulating creation of a notification. |
| 18 | + |
| 19 | +- Update `appSettings.json` with the `EventHubName` and `EventHubConnectionString` which you can find by going to your EventHub resource, creating an instance and then a `Shared Access Policy` |
| 20 | + |
| 21 | +### Azure Function - Event Handler |
| 22 | + |
| 23 | +This sample includes an example [EventHandler Azure Function](/samples/EnterpriseNotification/EventHandler) which is triggered by Event delivery and handles Event processing. |
| 24 | + |
| 25 | +1. Update [Function1.cs](/samples/EnterpriseNotification/EventHandler/Function1.cs) and change the `EventHubTrigger` to reflect your Event Hub name. |
| 26 | + ```csharp |
| 27 | + public static async Task Run([EventHubTrigger("YourEventHubName", Connection = "EventHubConnection")] EventData[] events, ILogger log)` |
| 28 | + ``` |
| 29 | +2. The Azure Functions blade in the Azure Portal provides a wide range of routes to deploy the provided code to your newly created Azure Function including Visual Studio and VSCode. Follow this to deploy the sample EventHandler project. |
| 30 | +3. Once deployed, go to the Azure Function in Azure and choose Configuration. |
| 31 | +4. Create a new `ConnectionString` called `EventHubConnection` property and provide the same EventHub connection string as in the previous section. |
| 32 | +5. In the `Application Settings` section create the following settings which are used bvy the Event Handler. |
| 33 | + - `DirectLineSecret` - Located within the Channels section of your Azure Bot Service registration. Required to communicate with your assistant and send events. |
| 34 | + - `DocumentDbEndpointUrl` - Located within the CosmoDB Azure Portal blade. Required to access the User Preference store. |
| 35 | + - `DocumentDbPrimaryKey`- Located within the CosmoDB Azure Portal blade. |
| 36 | + |
| 37 | +## Virtual Assistant |
| 38 | + |
| 39 | +### ProactiveState Middleware |
| 40 | + |
| 41 | +In order to be able to deliver messages to a conversation the end user must already have had an interaction with the assistant. As part of this interaction a `ConversationReference` needs to be persisted and used to resume the conversation. |
| 42 | + |
| 43 | +We provide a middleware component to perform this ConversationReference storage which can be found in the Bot.Builder.Solutions package. |
| 44 | + |
| 45 | +1. Add this line to your `Startup.cs` to register the proactive state. |
| 46 | +```csharp |
| 47 | + services.AddSingleton<ProactiveState>(); |
| 48 | +``` |
| 49 | +2. Within your `DefaultAdapter.cs` add this line to the constructor |
| 50 | +```csharp |
| 51 | + ProactiveState proactiveState |
| 52 | +``` |
| 53 | +3. Within your `DefaultAdapter.cs` add this line: |
| 54 | +```csharp |
| 55 | + Use(new ProactiveStateMiddleware(proactiveState)); |
| 56 | +``` |
| 57 | + |
| 58 | +### Event Handling |
| 59 | + |
| 60 | +The following code handles the `BroadcastEvent` event type sent by the Azure function and is added to the Event Handling code. Within Virtual Assistant this is handled by `OnEventAsync` within MainDialog.cs. |
| 61 | + |
| 62 | +The `_proactiveStateAccessor` is the state that contains a mapping between UserId and previously persisted conversation. It retrieves the proactive state from a store previously saved by enabling the `ProactiveStateMiddleware`. |
| 63 | + |
| 64 | +Within `MainDialog.cs` add the following changes: |
| 65 | + |
| 66 | +1. Add this variable to your `MainDialog` class. |
| 67 | + ```csharp |
| 68 | + private IStatePropertyAccessor<ProactiveModel> _proactiveStateAccessor; |
| 69 | + ``` |
| 70 | +2. Add this line to the constructor |
| 71 | + ```csharp |
| 72 | + ProactiveState proactiveState |
| 73 | + ``` |
| 74 | + and initialise the state in the constructor |
| 75 | + ```csharp |
| 76 | + _proactiveStateAccessor = proactiveState.CreateProperty<ProactiveModel>(nameof(ProactiveModel)); |
| 77 | + ``` |
| 78 | +3. Add this event handler to your `OnEventAsync` handler to handle the `BroadcastEvent` |
| 79 | + |
| 80 | + ```csharp |
| 81 | + case "BroadcastEvent": |
| 82 | + var eventData = JsonConvert.DeserializeObject<EventData>(dc.Context.Activity.Value.ToString()); |
| 83 | + |
| 84 | + var proactiveModel = await _proactiveStateAccessor.GetAsync(dc.Context, () => new ProactiveModel()); |
| 85 | + |
| 86 | + var conversationReference = proactiveModel[MD5Util.ComputeHash(eventData.UserId)].Conversation; |
| 87 | + await dc.Context.Adapter.ContinueConversationAsync(_appCredentials.MicrosoftAppId, conversationReference, ContinueConversationCallback(dc.Context, eventData.Message), cancellationToken); |
| 88 | + break; |
| 89 | + ``` |
| 90 | + |
| 91 | +## Testing |
| 92 | + |
| 93 | +With these changes in place, when an event is being sent to a user through the bot the user will get the message in the ongoing conversation in a channel. Follow the instructions below to test the end to end flow. |
| 94 | + |
| 95 | +### Bot Framework Emulator |
| 96 | + |
| 97 | +Event generation must generate Events with the same `UserId` as the Emulator is using so the existing conversation can be matched and notifications can be delivered. |
| 98 | + |
| 99 | +1. Using the [Bot Framework Emulator](https://github.com/Microsoft/BotFramework-Emulator) navigate to the Settings section and provide a Guid to represent your simulated UserId. This will ensure any conversations with your Assistant will use this UserId |
| 100 | +
|
| 101 | +  |
| 102 | +2. Start a conversation with your assistant which will ensure a proactive state record is persisted for future use. |
| 103 | + |
| 104 | +## Event Producer |
| 105 | + |
| 106 | +Update `SendMessagesToEventHub` within `Program.cs` of the example [EventProducer](/samples/EnterpriseNotification/EventProducer) project to change the UserId to the one created in the previous step. This will ensure any notifications sent are routed to your active conversation. |
| 107 | + |
| 108 | +Run the Event Producer to generate a message and observe that the message is shown within your Emulator session. |
| 109 | + |
| 110 | + |
0 commit comments