Skip to content
This repository was archived by the owner on Jun 30, 2022. It is now read-only.

Commit 425dcfa

Browse files
authored
enterprise notification sample (#1954)
* add notification sample * add architecture image and improve the doc * Documentation updates and testing * add proactive implementation into VirtualAssistant of the sample * updates * add cosmosdbproactive node * update * update * update skills package version * update
1 parent 6cded0f commit 425dcfa

File tree

125 files changed

+27511
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+27511
-0
lines changed

docs/media/emulator-userid.png

196 KB
Loading
300 KB
Loading
328 KB
Loading
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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+
![UserId Settings](/docs/media/emulator-userid.png)
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+
![Enterprise Notification Demo](/docs/media/enterprisenotification-demo.png)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29102.190
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventHandler", "EventHandler\EventHandler.csproj", "{CC6E0387-FED1-4D72-A089-6B2B81011A23}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualAssistant", "VirtualAssistant\VirtualAssistant.csproj", "{E0A0D813-0D6A-45D8-BF09-4F0AC0269FE3}"
9+
EndProject
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventProducer", "EventProducer\EventProducer.csproj", "{843204E6-EA50-4DFF-8B8B-E6814D8E6642}"
11+
EndProject
12+
Global
13+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
14+
Debug - NuGet Packages|Any CPU = Debug - NuGet Packages|Any CPU
15+
Debug|Any CPU = Debug|Any CPU
16+
Documentation|Any CPU = Documentation|Any CPU
17+
Release|Any CPU = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20+
{CC6E0387-FED1-4D72-A089-6B2B81011A23}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
21+
{CC6E0387-FED1-4D72-A089-6B2B81011A23}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
22+
{CC6E0387-FED1-4D72-A089-6B2B81011A23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{CC6E0387-FED1-4D72-A089-6B2B81011A23}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{CC6E0387-FED1-4D72-A089-6B2B81011A23}.Documentation|Any CPU.ActiveCfg = Debug|Any CPU
25+
{CC6E0387-FED1-4D72-A089-6B2B81011A23}.Documentation|Any CPU.Build.0 = Debug|Any CPU
26+
{CC6E0387-FED1-4D72-A089-6B2B81011A23}.Release|Any CPU.ActiveCfg = Release|Any CPU
27+
{CC6E0387-FED1-4D72-A089-6B2B81011A23}.Release|Any CPU.Build.0 = Release|Any CPU
28+
{E0A0D813-0D6A-45D8-BF09-4F0AC0269FE3}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
29+
{E0A0D813-0D6A-45D8-BF09-4F0AC0269FE3}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
30+
{E0A0D813-0D6A-45D8-BF09-4F0AC0269FE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31+
{E0A0D813-0D6A-45D8-BF09-4F0AC0269FE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
32+
{E0A0D813-0D6A-45D8-BF09-4F0AC0269FE3}.Documentation|Any CPU.ActiveCfg = Debug|Any CPU
33+
{E0A0D813-0D6A-45D8-BF09-4F0AC0269FE3}.Documentation|Any CPU.Build.0 = Debug|Any CPU
34+
{E0A0D813-0D6A-45D8-BF09-4F0AC0269FE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
35+
{E0A0D813-0D6A-45D8-BF09-4F0AC0269FE3}.Release|Any CPU.Build.0 = Release|Any CPU
36+
{843204E6-EA50-4DFF-8B8B-E6814D8E6642}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
37+
{843204E6-EA50-4DFF-8B8B-E6814D8E6642}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
38+
{843204E6-EA50-4DFF-8B8B-E6814D8E6642}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39+
{843204E6-EA50-4DFF-8B8B-E6814D8E6642}.Debug|Any CPU.Build.0 = Debug|Any CPU
40+
{843204E6-EA50-4DFF-8B8B-E6814D8E6642}.Documentation|Any CPU.ActiveCfg = Debug|Any CPU
41+
{843204E6-EA50-4DFF-8B8B-E6814D8E6642}.Documentation|Any CPU.Build.0 = Debug|Any CPU
42+
{843204E6-EA50-4DFF-8B8B-E6814D8E6642}.Release|Any CPU.ActiveCfg = Release|Any CPU
43+
{843204E6-EA50-4DFF-8B8B-E6814D8E6642}.Release|Any CPU.Build.0 = Release|Any CPU
44+
EndGlobalSection
45+
GlobalSection(SolutionProperties) = preSolution
46+
HideSolutionNode = FALSE
47+
EndGlobalSection
48+
GlobalSection(ExtensibilityGlobals) = postSolution
49+
SolutionGuid = {0CBBA70E-7242-4EC3-A76B-FF444246A980}
50+
EndGlobalSection
51+
EndGlobal

0 commit comments

Comments
 (0)