Skip to content

Commit c1e4f88

Browse files
authored
Update SignalR samples (#1250)
1 parent f5a232c commit c1e4f88

File tree

4 files changed

+132
-8
lines changed

4 files changed

+132
-8
lines changed
Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,42 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

4+
using System.Text.Json;
45
using Microsoft.Azure.Functions.Worker;
56
using Microsoft.Azure.Functions.Worker.Http;
67

78
namespace Extensions.SignalR
89
{
910
public static class SignalRNegotiationFunctions
1011
{
12+
// <snippet_negotiate>
1113
[Function("Negotiate")]
12-
public static SignalRConnectionInfo Negotiate(
13-
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req,
14-
[SignalRConnectionInfoInput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")] SignalRConnectionInfo connectionInfo)
14+
public static string Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
15+
[SignalRConnectionInfoInput(HubName = "serverless")] string connectionInfo)
1516
{
17+
// The serialization of the connection info object is done by the framework. It should be camel case. The SignalR client respects the camel case response only.
1618
return connectionInfo;
1719
}
20+
// </snippet_negotiate>
21+
1822

1923
// When you have multiple SignalR service instances and you want to customize the rule that route a client
24+
// <snippet_negotiate_multiple_endpoint>
25+
public static readonly JsonSerializerOptions SerializerOptions = new()
26+
{
27+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
28+
};
2029
[Function("NegotiateWithMultipleEndpoints")]
21-
public static SignalRConnectionInfo NegotiateWithMultipleEndpoints(
30+
public static string NegotiateWithMultipleEndpoints(
2231
[HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
2332
[SignalRNegotiationInput("chatHub", "SignalRConnection")] SignalRNegotiationContext negotiationContext)
2433
{
25-
// customize your rule here
26-
return negotiationContext.Endpoints[0].ConnectionInfo;
34+
// Customize your rule here
35+
var connectionInfo = negotiationContext.Endpoints[0].ConnectionInfo;
36+
// The SignalR client respects the camel case response only.
37+
return JsonSerializer.Serialize(connectionInfo, SerializerOptions);
2738
}
39+
// </snippet_negotiate_multiple_endpoint>
40+
2841
}
2942
}

samples/Extensions/SignalR/SignalROutputBindingFunctions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ public static class SignalROutputBindingFunctions
1212
{
1313
[Function("BroadcastToAll")]
1414
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
15-
public static SignalRMessageAction BroadcastToAll([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
15+
public static SignalRMessageAction BroadcastToAll(
16+
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
1617
{
1718
using var bodyReader = new StreamReader(req.Body);
1819
return new SignalRMessageAction("newMessage")
@@ -24,7 +25,8 @@ public static SignalRMessageAction BroadcastToAll([HttpTrigger(AuthorizationLeve
2425

2526
[Function("SendToConnection")]
2627
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
27-
public static SignalRMessageAction SendToConnection([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
28+
public static SignalRMessageAction SendToConnection(
29+
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
2830
{
2931
using var bodyReader = new StreamReader(req.Body);
3032
return new SignalRMessageAction("newMessage")
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System.IO;
5+
using System.Linq;
6+
using Microsoft.Azure.Functions.Worker;
7+
using Microsoft.Azure.Functions.Worker.Http;
8+
9+
namespace SampleApp
10+
{
11+
/// <summary>
12+
/// The class is the same as SignalROutputBindingFunctions except the comments. Just keep the original one because the learn website refers to it.
13+
/// </summary>
14+
public static class SignalROutputBindingFunctions2
15+
{
16+
// <snippet_broadcast_to_all>
17+
[Function("BroadcastToAll")]
18+
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
19+
public static SignalRMessageAction BroadcastToAll([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
20+
{
21+
using var bodyReader = new StreamReader(req.Body);
22+
return new SignalRMessageAction("newMessage")
23+
{
24+
// broadcast to all the connected clients without specifying any connection, user or group.
25+
Arguments = new[] { bodyReader.ReadToEnd() },
26+
};
27+
}
28+
// </snippet_broadcast_to_all>
29+
30+
// <snippet_send_to_connection>
31+
[Function("SendToConnection")]
32+
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
33+
public static SignalRMessageAction SendToConnection([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
34+
{
35+
using var bodyReader = new StreamReader(req.Body);
36+
return new SignalRMessageAction("newMessage")
37+
{
38+
Arguments = new[] { bodyReader.ReadToEnd() },
39+
ConnectionId = "connectionToSend",
40+
};
41+
}
42+
// </snippet_send_to_connection>
43+
44+
// <snippet_send_to_user>
45+
[Function("SendToUser")]
46+
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
47+
public static SignalRMessageAction SendToUser([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
48+
{
49+
using var bodyReader = new StreamReader(req.Body);
50+
return new SignalRMessageAction("newMessage")
51+
{
52+
Arguments = new[] { bodyReader.ReadToEnd() },
53+
UserId = "userToSend",
54+
};
55+
}
56+
// </snippet_send_to_user>
57+
58+
// <snippet_send_to_group>
59+
[Function("SendToGroup")]
60+
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
61+
public static SignalRMessageAction SendToGroup([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
62+
{
63+
using var bodyReader = new StreamReader(req.Body);
64+
return new SignalRMessageAction("newMessage")
65+
{
66+
Arguments = new[] { bodyReader.ReadToEnd() },
67+
GroupName = "groupToSend"
68+
};
69+
}
70+
// </snippet_send_to_group>
71+
72+
// <snippet_send_to_endpoint>
73+
[Function("SendToEndpoint")]
74+
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
75+
public static SignalRMessageAction SendToEndpoint(
76+
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req,
77+
[SignalREndpointsInput("chat", ConnectionStringSetting = "SignalRConnection")] SignalREndpoint[] endpoints)
78+
{
79+
using var bodyReader = new StreamReader(req.Body);
80+
return new SignalRMessageAction("newMessage")
81+
{
82+
Arguments = new[] { bodyReader.ReadToEnd() },
83+
// Only send to primary endpoint if you have configured multiple SignalR Service instances.
84+
// The use of 'Endpoints' can be combined with other properties such as UserId, GroupName, ConnectionID.
85+
Endpoints = endpoints.Where(e => e.EndpointType == SignalREndpointType.Primary).ToArray()
86+
};
87+
}
88+
// </snippet_send_to_endpoint>
89+
90+
// <snippet_remove_from_group>
91+
[Function("RemoveFromGroup")]
92+
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
93+
public static SignalRGroupAction RemoveFromGroup([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
94+
{
95+
return new SignalRGroupAction(SignalRGroupActionType.Remove)
96+
{
97+
GroupName = "group1",
98+
UserId = "user1"
99+
};
100+
}
101+
// </snippet_remove_from_group>
102+
}
103+
}

samples/Extensions/SignalR/SignalRTriggerFunctions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,31 @@ namespace Extensions.SignalR
99
{
1010
public static class SignalRTriggerFunctions
1111
{
12+
// <snippet_on_connected>
1213
[Function("OnConnected")]
1314
public static void OnConnected([SignalRTrigger("chat", "connections", "connected", ConnectionStringSetting = "SignalRConnection")] SignalRInvocationContext invocationContext, FunctionContext functionContext)
1415
{
1516
var logger = functionContext.GetLogger("OnConnected");
1617
logger.LogInformation($"Connection {invocationContext.ConnectionId} is connected");
1718
}
19+
// </snippet_on_connected>
1820

21+
// <snippet_on_disconnected>
1922
[Function("OnDisconnected")]
2023
public static void OnDisconnected([SignalRTrigger("chat", "connections", "disconnected", ConnectionStringSetting = "SignalRConnection")] SignalRInvocationContext invocationContext, FunctionContext functionContext)
2124
{
2225
var logger = functionContext.GetLogger("OnDisconnected");
2326
logger.LogInformation($"Connection {invocationContext.ConnectionId} is disconnected. Error: {invocationContext.Error}");
2427
}
28+
// </snippet_on_disconnected>
2529

30+
// <snippet_on_message>
2631
[Function("OnClientMessage")]
2732
public static void OnClientMessage([SignalRTrigger("Hub", "messages", "sendMessage", "content", ConnectionStringSetting = "SignalRConnection")] SignalRInvocationContext invocationContext, string content, FunctionContext functionContext)
2833
{
2934
var logger = functionContext.GetLogger("OnClientMessage");
3035
logger.LogInformation($"Connection {invocationContext.ConnectionId} sent a message. Message content: {content}");
3136
}
37+
// </snippet_on_message>
3238
}
3339
}

0 commit comments

Comments
 (0)