Skip to content

Commit 4321dcc

Browse files
authored
Update API of ServerlessHub<T> according to the review meeting (Azure#25834)
* Update API of ServerlessHub<T> according to the review meeting * Rename `Event` -> `SignalRTriggerEvents`, `Category` -> `SignalRTriggerCategories` * Update Azure SignalR SDK to 1.15.0 Why TFM .netcoreapp3.1 deleted: The `JsonHubProtocol` of ASP.NET SignalR uses `Newtonsoft.Json` for netcoreapp 2.1 and uses `System.Text.Json` for netcore3.1 and above. However, function host always uses `Newtonsoft.Json` to parse JSON data sent from isolated worker, and SignalR fails to serialize `Newtonsoft.Json.JObject` on .NET Core 3.1 correctly. In the past, SignalR SDK and extensions enabled `NewtonsoftJsonHubProtocol` (not available on .NET Core 2.1) on .NET Core 3.1 with isolated function workers only, so they had to use framework-sensitive conditional compilation. Since SignalR SDK 1.15.0, we have a new hub protocol accepting a `ObjectSerializer`, which is available on .NET Standard 2.0, so framework-sensitive conditional is unecessary. * Update * Add `SignalRConnectionAttribute` for `ServerlessHub<T>` * Fix for SignalRConnectionAttribute * Fix * Remove unused using.
1 parent 1c6d93c commit 4321dcc

28 files changed

+409
-498
lines changed

eng/Packages.Data.props

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,9 @@
119119
<PackageReference Update="Apache.Avro" Version="1.11.0" />
120120
<PackageReference Update="CloudNative.CloudEvents" Version="2.0.0" />
121121
<PackageReference Update="CloudNative.CloudEvents.SystemTextJson" Version="2.0.0" />
122-
<PackageReference Update="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="3.0.0" Condition="'$(TargetFramework)' == 'netcoreapp3.1'" />
123-
<PackageReference Update="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="5.0.1" Condition="'$(TargetFramework)' == 'net5.0'" />
124-
<PackageReference Update="Microsoft.Azure.SignalR" Version="1.13.0" />
125-
<PackageReference Update="Microsoft.Azure.SignalR.Management" Version="1.13.0" />
126-
<PackageReference Update="Microsoft.Azure.SignalR.Protocols" Version="1.13.0" />
122+
<PackageReference Update="Microsoft.Azure.SignalR" Version="1.15.0" />
123+
<PackageReference Update="Microsoft.Azure.SignalR.Management" Version="1.15.0" />
124+
<PackageReference Update="Microsoft.Azure.SignalR.Protocols" Version="1.15.0" />
127125
<PackageReference Update="Microsoft.Azure.SignalR.Serverless.Protocols" Version="1.6.0" />
128126
<PackageReference Update="Microsoft.Azure.WebJobs" Version="3.0.31" />
129127
<PackageReference Update="Microsoft.Azure.WebJobs.Sources" Version="3.0.30" />

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/Microsoft.Azure.WebJobs.Extensions.SignalRService.sln

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.WebJobs.Ext
1414
EndProject
1515
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Api", "Api", "{25AE2C7A-FD10-4A94-A063-857C542B7D45}"
1616
ProjectSection(SolutionItems) = preProject
17-
api\Microsoft.Azure.WebJobs.Extensions.SignalRService.netcoreapp3.1.cs = api\Microsoft.Azure.WebJobs.Extensions.SignalRService.netcoreapp3.1.cs
1817
api\Microsoft.Azure.WebJobs.Extensions.SignalRService.netstandard2.0.cs = api\Microsoft.Azure.WebJobs.Extensions.SignalRService.netstandard2.0.cs
1918
EndProjectSection
2019
EndProject

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/api/Microsoft.Azure.WebJobs.Extensions.SignalRService.netcoreapp3.1.cs

Lines changed: 0 additions & 271 deletions
This file was deleted.

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/api/Microsoft.Azure.WebJobs.Extensions.SignalRService.netstandard2.0.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
22
{
3+
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
34
public static partial class Category
45
{
56
public const string Connections = "connections";
67
public const string Messages = "messages";
78
}
9+
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
810
public static partial class Event
911
{
1012
public const string Connected = "connected";
@@ -114,12 +116,14 @@ public SignalRConnectionAttribute(string connectionStringSetting) { }
114116
}
115117
public abstract partial class ServerlessHub<T> where T : class
116118
{
117-
protected ServerlessHub(Microsoft.Azure.SignalR.Management.ServiceHubContext<T> serviceHubContext = null) { }
119+
protected ServerlessHub() { }
120+
protected ServerlessHub(Microsoft.Azure.SignalR.Management.ServiceHubContext<T> serviceHubContext) { }
118121
public Microsoft.Azure.SignalR.Management.ClientManager ClientManager { get { throw null; } }
119122
public Microsoft.AspNetCore.SignalR.IHubClients<T> Clients { get { throw null; } }
120123
public Microsoft.Azure.SignalR.Management.GroupManager Groups { get { throw null; } }
124+
public string HubName { get { throw null; } }
121125
public Microsoft.Azure.SignalR.Management.UserGroupManager UserGroups { get { throw null; } }
122-
protected static System.Collections.Generic.IList<System.Security.Claims.Claim> GetClaims(string jwt) { throw null; }
126+
protected System.Collections.Generic.IList<System.Security.Claims.Claim> GetClaims(string jwt) { throw null; }
123127
protected System.Threading.Tasks.Task<Microsoft.Azure.WebJobs.Extensions.SignalRService.SignalRConnectionInfo> NegotiateAsync(Microsoft.Azure.SignalR.Management.NegotiationOptions options) { throw null; }
124128
}
125129
public partial class SignalRAsyncCollector<T> : Microsoft.Azure.WebJobs.IAsyncCollector<T>
@@ -137,6 +141,12 @@ public SignalRAttribute() { }
137141
[Microsoft.Azure.WebJobs.Description.AutoResolveAttribute]
138142
public string HubName { get { throw null; } set { } }
139143
}
144+
[System.AttributeUsageAttribute(System.AttributeTargets.Class)]
145+
public partial class SignalRConnectionAttribute : System.Attribute, Microsoft.Azure.WebJobs.IConnectionProvider
146+
{
147+
public SignalRConnectionAttribute(string connection) { }
148+
public string Connection { get { throw null; } set { } }
149+
}
140150
public partial class SignalRConnectionDetail
141151
{
142152
public SignalRConnectionDetail() { }
@@ -249,6 +259,16 @@ public SignalRTriggerAttribute(string hubName, string category, string @event, p
249259
public string HubName { get { throw null; } }
250260
public string[] ParameterNames { get { throw null; } }
251261
}
262+
public static partial class SignalRTriggerCategories
263+
{
264+
public const string Connections = "connections";
265+
public const string Messages = "messages";
266+
}
267+
public static partial class SignalRTriggerEvents
268+
{
269+
public const string Connected = "connected";
270+
public const string Disconnected = "disconnected";
271+
}
252272
public partial class SignalRTriggerException : System.Exception
253273
{
254274
public SignalRTriggerException() { }

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Category.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
using System.ComponentModel;
5+
46
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
57
{
68
/// <summary>
79
/// A class contains constant strings that represent SignalR trigger category.
810
/// </summary>
911
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "AZC0012:Avoid single word type names", Justification = "Breaking change")]
12+
[EditorBrowsable(EditorBrowsableState.Never)]
1013
public static class Category
1114
{
1215
/// <summary>

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Config/DependencyInjectionExtensions.cs

Lines changed: 0 additions & 50 deletions
This file was deleted.
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
3-
#if NETCOREAPP3_1
4-
using Microsoft.AspNetCore.SignalR.Protocol;
53

64
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
75
{
86
internal enum HubProtocol
97
{
108
/// <summary>
119
/// Implements the SignalR Hub Protocol using System.Text.Json.
12-
/// <see cref="JsonHubProtocol"/>
1310
/// </summary>
1411
SystemTextJson,
1512

1613
/// <summary>
1714
/// Implements the SignalR Hub Protocol using Newtonsoft.Json.
18-
/// <see cref="NewtonsoftJsonHubProtocol "/>
1915
/// </summary>
2016
NewtonsoftJson
2117
}
22-
}
23-
#endif
18+
}

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Config/IConfigurationExtensions.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using Azure.Core.Serialization;
67
using Microsoft.Azure.SignalR;
78
using Microsoft.Extensions.Azure;
89
using Microsoft.Extensions.Configuration;
10+
using Newtonsoft.Json;
11+
using Newtonsoft.Json.Serialization;
912

1013
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
1114
{
@@ -65,5 +68,45 @@ public static bool TryGetNamedEndpointFromIdentity(this IConfigurationSection se
6568
endpoint = null;
6669
return false;
6770
}
71+
72+
public static bool TryGetJsonObjectSerializer(this IConfiguration configuration, out ObjectSerializer serializer)
73+
{
74+
//indicates Newtonsoft, camcelCase
75+
if (configuration.GetValue(Constants.AzureSignalRNewtonsoftCamelCase, false))
76+
{
77+
serializer = new NewtonsoftJsonObjectSerializer(new JsonSerializerSettings()
78+
{
79+
ContractResolver = new CamelCasePropertyNamesContractResolver()
80+
});
81+
return true;
82+
}
83+
84+
if (!configuration.OnDotnetInProcessRuntime())
85+
{
86+
serializer = new NewtonsoftJsonObjectSerializer();
87+
return true;
88+
}
89+
90+
var hubProtocolConfig = configuration[Constants.AzureSignalRHubProtocol];
91+
if (hubProtocolConfig is not null)
92+
{
93+
serializer = Enum.Parse(typeof(HubProtocol), hubProtocolConfig, true) switch
94+
{
95+
HubProtocol.NewtonsoftJson => new NewtonsoftJsonObjectSerializer(),
96+
HubProtocol.SystemTextJson => new JsonObjectSerializer(),
97+
_ => throw new NotSupportedException($"The {Constants.AzureSignalRHubProtocol} setting value '{hubProtocolConfig}' is not supported."),
98+
};
99+
return true;
100+
}
101+
serializer = null;
102+
return false;
103+
}
104+
105+
private static bool OnDotnetInProcessRuntime(this IConfiguration configuration)
106+
{
107+
var workerRuntime = configuration[Constants.FunctionsWorkerRuntime];
108+
//unit test environment
109+
return workerRuntime == null || workerRuntime == Constants.DotnetWorker;
110+
}
68111
}
69112
}

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Config/OptionsSetup.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public OptionsSetup(IConfiguration configuration, ILoggerFactory loggerFactory,
4242

4343
public void Configure(ServiceManagerOptions options)
4444
{
45+
if (_configuration.TryGetJsonObjectSerializer(out var serializer))
46+
{
47+
options.UseJsonObjectSerializer(serializer);
48+
}
49+
4550
options.ConnectionString = _configuration.GetConnectionString(_connectionStringKey) ?? _configuration[_connectionStringKey];
4651
var endpoints = _configuration.GetSection(Constants.AzureSignalREndpoints).GetEndpoints(_azureComponentFactory);
4752
// Fall back to use a section to configure Azure identity

sdk/signalr/Microsoft.Azure.WebJobs.Extensions.SignalRService/src/Config/ServiceManagerStore.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ private IInternalServiceHubContextStore CreateHubContextStore(string connectionS
6565
{
6666
services.AddSingleton(_router);
6767
}
68-
services.SetHubProtocol(_configuration);
6968
services.AddSingleton(services.ToList() as IReadOnlyCollection<ServiceDescriptor>);
7069
return services.BuildServiceProvider()
7170
.GetRequiredService<IInternalServiceHubContextStore>();

0 commit comments

Comments
 (0)