You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
2. Then add `app.UseStaticFiles();` before `app.UseRouting();`in`Startup.cs` to support static files. Remove the default `endpoints.MapGet` inside `app.UseEndpoints`.
87
-
88
-
```csharp
89
-
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
90
-
{
91
-
if (env.IsDevelopment())
92
-
{
93
-
app.UseDeveloperExceptionPage();
94
-
}
95
-
96
-
app.UseStaticFiles();
97
-
app.UseRouting();
98
-
99
-
app.UseEndpoints(endpoints =>
100
-
{
101
-
});
102
-
}
103
-
```
104
-
105
-
3. Also create an HTML file and save it as `wwwroot/index.html`, we'll use it for the UI of the chat app later.
106
-
107
-
```html
108
-
<html>
109
-
<body>
110
-
<h1>Azure Web PubSub Chat</h1>
111
-
</body>
112
-
</html>
113
-
```
114
-
115
-
You can test the server by running `dotnet run --urls http://localhost:8080` and access http://localhost:8080/index.html in browser.
116
-
117
-
You may remember in the [publish and subscribe message tutorial](./tutorial-pub-sub-messages.md) the subscriber uses an API in Web PubSub SDK to generate an access token from connection string and use it to connect to the service. This is usually not safe in a real world application as connection string has high privilege to do any operation to the service so you don't want to share it with any client. Let's change this access token generation process to a REST API at server side, so client can call this API to request an access token every time it needs to connect, without need to hold the connection string.
118
-
119
-
1. Install dependencies.
120
-
121
-
```bash
122
-
dotnet add package Microsoft.Extensions.Azure
123
-
```
124
-
125
-
2. Add a `SampleChatHub` class to handle hub events. And DI the service middleware and service client inside `ConfigureServices()`. Don't forget to replace `<connection_string>` with the one of your services.
126
-
127
-
```csharp
128
-
public void ConfigureServices(IServiceCollection services)
129
-
{
130
-
services.AddWebPubSub(o => o.ServiceEndpoint = new ServiceEndpoint("<connection_string>"))
131
-
.AddWebPubSubServiceClient<SampleChatHub>();
132
-
}
133
-
134
-
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
135
-
{
136
-
if (env.IsDevelopment())
137
-
{
138
-
app.UseDeveloperExceptionPage();
139
-
}
140
-
141
-
app.UseStaticFiles();
142
-
app.UseRouting();
143
-
144
-
app.UseEndpoints(endpoints =>
145
-
{
146
-
});
147
-
}
148
-
149
-
private sealed class SampleChatHub : WebPubSubHub
150
-
{
151
-
}
152
-
```
153
-
154
-
`AddWebPubSubServiceClient<THub>()` is used to inject the service client `WebPubSubServiceClient<THub>`, with which we can use in negotiation step to generate client connection token and in hub methods to invoke service REST APIs when hub events are triggered.
155
-
156
-
3. Add a `/negotiate` API to the server inside `app.UseEndpoints` to generate the token.
157
-
158
-
```csharp
159
-
app.UseEndpoints(endpoints =>
160
-
{
161
-
endpoints.MapGet("/negotiate", async context =>
162
-
{
163
-
var id = context.Request.Query["id"];
164
-
if (id.Count != 1)
165
-
{
166
-
context.Response.StatusCode = 400;
167
-
await context.Response.WriteAsync("missing user id");
168
-
return;
169
-
}
170
-
var serviceClient = context.RequestServices.GetRequiredService<WebPubSubServiceClient<SampleChatHub>>();
This token generation code is similar to the one we used in the [publish and subscribe message tutorial](./tutorial-pub-sub-messages.md), except we pass one more argument (`userId`) when generating the token. User ID can be used to identify the identity of client so when you receive a message you know where the message is coming from.
177
-
178
-
You can test this API by running `dotnet run --urls http://localhost:8080` and accessing `http://localhost:8080/negotiate?id=<user-id>` and it will give you the full url of the Azure Web PubSub with an access token.
179
-
180
-
4. Then update `index.html` to include the following script to get the token from server and connect to service.
181
-
182
-
```html
183
-
<html>
184
-
<body>
185
-
<h1>Azure Web PubSub Chat</h1>
186
-
</body>
187
-
188
-
<script>
189
-
(async function() {
190
-
let id = prompt('Please input your user name');
191
-
let res = await fetch(`/negotiate?id=${id}`);
192
-
let url = await res.text();
193
-
let ws = new WebSocket(url);
194
-
ws.onopen = () => console.log('connected');
195
-
})();
196
-
</script>
197
-
</html>
198
-
```
199
-
200
-
If you are using Chrome, you can test it by opening the home page, input your user name. Press F12 to open the Developer Tools window, switch to **Console** table and you'll see `connected` being printed in browser console.
201
-
202
-
# [C# .NET 6](#tab/net6)
203
71
We'll use [ASP.NET Core 6](/aspnet/core) to host the web pages and handle incoming requests.
204
72
205
73
First let's create an empty ASP.NET Core app.
@@ -210,15 +78,14 @@ First let's create an empty ASP.NET Core app.
2. Remove the default `app.MapGet("/", () => "Hello World!");` in `Program.cs` and by replacing it by the following code snippet.
81
+
2. Replace the default app.MapGet() in Program.cs with following code snippet.
214
82
215
83
``` csharp
216
84
if (app.Environment.IsDevelopment())
217
85
{
218
86
app.UseDeveloperExceptionPage();
219
87
}
220
88
221
-
app.UseDefaultFiles();
222
89
app.UseStaticFiles();
223
90
app.UseRouting();
224
91
@@ -247,17 +114,7 @@ You may remember in the [publish and subscribe message tutorial](./tutorial-pub-
247
114
dotnet add package Microsoft.Extensions.Azure
248
115
```
249
116
250
-
2. Create a file `SampleChatHub.cs`for the `SampleChatHub` class to handle hub events with the following content.
251
-
252
-
```csharp
253
-
using Microsoft.Azure.WebPubSub.AspNetCore;
254
-
255
-
sealed class SampleChatHub : WebPubSubHub
256
-
{
257
-
}
258
-
```
259
-
260
-
3. Then update the `Program.cs` file to add DI for the service middleware and service client inside. Don't forget to replace `<connection_string>` with the one of your services.
117
+
2. Add a `SampleChatHub` class to handle hub events. Add DI for the service middleware and service client. Don't forget to replace `<connection_string>` with the one of your services.
261
118
262
119
```csharp
263
120
using Microsoft.Azure.WebPubSub.AspNetCore;
@@ -283,7 +140,11 @@ You may remember in the [publish and subscribe message tutorial](./tutorial-pub-
283
140
{
284
141
});
285
142
286
-
app.Run();
143
+
app.Run();
144
+
145
+
sealed class SampleChatHub : WebPubSubHub
146
+
{
147
+
}
287
148
```
288
149
289
150
`AddWebPubSubServiceClient<THub>()` is used to inject the service client `WebPubSubServiceClient<THub>`, with which we can use in negotiation step to generate client connection token and in hub methods to invoke service REST APIs when hub events are triggered.
@@ -324,7 +185,7 @@ You may remember in the [publish and subscribe message tutorial](./tutorial-pub-
324
185
let id = prompt('Please input your user name');
325
186
let res = await fetch(`/negotiate?id=${id}`);
326
187
let url = await res.text();
327
-
let ws = new WebSocket(url);
188
+
let ws = new WebSocket(url);+
328
189
ws.onopen = () => console.log('connected');
329
190
})();
330
191
</script>
@@ -626,40 +487,10 @@ Events are delivered to server in the form of Webhook. Webhook is served and exp
626
487
Azure Web PubSub follows [CloudEvents](./reference-cloud-events.md) to describe the event data.
627
488
628
489
# [C#](#tab/csharp)
629
-
Here we're using Web PubSub middleware SDK, there is already an implementation to parse and process CloudEvents schema, so we don't need to deal with these details. Instead, we can focus on the inner business logic in the hub methods.
630
-
631
-
1. Add event handlers inside `UseEndpoints`. Specify the endpoint path for the events, let's say `/eventhandler`.
2. Go the `SampleChatHub` we created in previous step. Add a constructor to work with `WebPubSubServiceClient<SampleChatHub>` so we can use to invoke service. And override `OnConnectedAsync()` method to respond when `connected` event is triggered.
In the above code, we use the service client to broadcast a notification message to all of whom is joined.
658
-
659
-
# [C# .NET 6](#tab/net6)
660
491
Here we're using Web PubSub middleware SDK, there is already an implementation to parse and process CloudEvents schema, so we don't need to deal with these details. Instead, we can focus on the inner business logic in the hub methods.
661
492
662
-
1. Add event handlers inside `UseEndpoints`. Specify the endpoint path for the events, let's say `/eventhandler`.
493
+
1. Add event handlers inside `UseEndpoints`. Specify the endpoint path for the events, let's say `/eventhandler`. The `UseEndpoints` should look like follows:
663
494
```csharp
664
495
app.UseEndpoints(endpoints =>
665
496
{
@@ -682,9 +513,6 @@ Here we're using Web PubSub middleware SDK, there is already an implementation t
682
513
2. Go the `SampleChatHub` we created in previous step. Add a constructor to work with `WebPubSubServiceClient<SampleChatHub>` so we can use to invoke service. And override `OnConnectedAsync()` method to respond when `connected` event is triggered.
This event handler uses `WebPubSubServiceClient.SendToAllAsync()` to broadcast the received message to all clients. You can see in the end we returned `UserEventResponse`, which contains a message directly to the caller and make the WebHook request success. If you have extra logic to validate and would like to break this call, you can throw an exception here. The middleware will deliver the exception message to service and service will drop current client connection.
834
-
835
-
2. Update `index.html` to add the logic to send message from user to server and display received messages in the page.
836
-
837
-
```html
838
-
<html>
839
-
840
-
<body>
841
-
<h1>Azure Web PubSub Chat</h1>
842
-
<input id="message" placeholder="Type to chat...">
843
-
<div id="messages"></div>
844
-
<script>
845
-
(async function () {
846
-
let id = prompt('Please input your user name');
847
-
let res = await fetch(`/negotiate?id=${id}`);
848
-
let url = await res.text();
849
-
let ws = new WebSocket(url);
850
-
ws.onopen = () => console.log('connected');
851
-
852
-
let messages = document.querySelector('#messages');
853
-
ws.onmessage = event => {
854
-
let m = document.createElement('p');
855
-
m.innerText = event.data;
856
-
messages.appendChild(m);
857
-
};
858
-
859
-
let message = document.querySelector('#message');
860
-
message.addEventListener('keypress', e => {
861
-
if (e.charCode !== 13) return;
862
-
ws.send(message.value);
863
-
message.value = '';
864
-
});
865
-
})();
866
-
</script>
867
-
</body>
868
-
869
-
</html>
870
-
```
871
-
872
-
You can see in the above code we use `WebSocket.send()` to send message and `WebSocket.onmessage` to listen to message from service.
873
-
874
-
Now run the server using `dotnet run --urls http://localhost:8080` and open multiple browser instances to access http://localhost:8080/index.html, then you can chat with each other.
875
-
876
-
The complete code sample of this tutorial can be found [here][code-csharp].
633
+
Implement the OnMessageReceivedAsync() method in SampleChatHub.
877
634
878
-
# [C# .NET 6](#tab/net6)
879
635
1. Handle message event.
880
636
881
637
```csharp
@@ -945,7 +701,7 @@ The complete code sample of this tutorial can be found [here][code-csharp].
945
701
946
702
Now run the server using `dotnet run --urls http://localhost:8080` and open multiple browser instances to access http://localhost:8080/index.html, then you can chat with each other.
947
703
948
-
The complete code sample of this tutorial can be found [here][code-csharp-net6].
704
+
The complete code sample of this tutorial can be found [here][code-csharp-net6], the ASP.NET Core 3.1 version [here][code-csharp].
949
705
950
706
# [JavaScript](#tab/javascript)
951
707
@@ -1180,4 +936,4 @@ Check other tutorials to further dive into how to use the service.
0 commit comments