System.Text.Json is now the default Hub Protocol used by SignalR clients and servers starting in ASP.NET Core 3.0-preview5.
This is my configuration in preview4:
services.AddSignalR().AddNewtonsoftJsonProtocol(options =>
{
options.PayloadSerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
How to migrate this in order to ignore NullValueHandling and ReferenceLoopHandling for SignalR JSON Protocol in preview5?
I believe System.Text.Json does not currently suppport an equivalent to ReferenceLoopHandling and likely won't support it in 3.0. @joshfree / @ahsonkhan do you know if there's an issue discussing adding this functionality in the future?
This is a good case where you probably want to continue using Newtonsoft.Json for now. We know that System.Text.Json will not cover all the same cases as Newtonsoft.Json (at least in the initial 3.0 release), so the Newtonsoft.Json package is going to remain in place and fully supported.
For NullValueHandling you can do something similar with this code:
services.AddSignalR()
.AddJsonProtocol(options => {
options.PayloadSerializerOptions.IgnoreNullValues = true;
});
I am using https://github.com/dotnet/corefx/issues/36510 to track cyclic references.
You will need to add a reference to "Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" starting in preview5 if you want to continue using Newtonsoft.Json.
FYI @steveharter
I added services.AddNewtonsoftJsonProtocol on my server-side setup. After adding Newtonsoft, both JsonHubProtocol and NewtonsoftJsonHubProtocol are in the available protocols found in DefaultHubProtocolResolver.
How do I configure the Javascript client to use the Newtonsoft Protocol rather than System.Text.Json? Running into an issue with cyclic references from the new default System.Text.Json.
Installed packages:
Try not to mix preview versions. There were a lot of changes between preview4 and preview9. If you update to preview9 you probably wont see issues anymore.
Oops, that was my bad there. I removed that package as we are not using it. However, still seeing SignalR preferring JsonHubProtocol over NewtonsoftJsonHubProtocol.
Here is my relevant code for adding SignalR to my application:
ISignalRServerBuilder builder = services.AddSignalR(options => options.EnableDetailedErrors = enableDetailedLogging);
if (environment.IsProduction())
{
builder.AddAzureSignalR(options => options.Endpoints = new ServiceEndpoint[]
{
new ServiceEndpoint(connectionStringConfig["AzureSignalR"], EndpointType.Primary, "Primary"),
new ServiceEndpoint(connectionStringConfig["AzureSignalRSecondary"], EndpointType.Secondary, "Secondary"),
});
}
else
{
builder.AddAzureSignalR(connectionStringConfig["AzureSignalR"]);
}
builder.AddNewtonsoftJsonProtocol(options =>
{
options.PayloadSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver {NamingStrategy = {OverrideSpecifiedNames = false}};
options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
While debugging, I found this method from Microsoft.Azure.SignalR.ServiceLifetimeManagerBase in the call stack which seems to be how I am ending up in System.Text.Json.
Both JsonHubProtocol and NewtonsoftJsonHubProtocol are in _allProtocols. I have a hacky workaround to remove JsonHubProtocol from the protocol resolver but probably do not want to keep that long-term 馃槃
protected IDictionary<string, ReadOnlyMemory<byte>> SerializeAllProtocols(string method, object[] args)
{
var payloads = new Dictionary<string, ReadOnlyMemory<byte>>();
var message = new InvocationMessage(method, args);
foreach (var hubProtocol in _allProtocols)
{
payloads.Add(hubProtocol.Name, hubProtocol.GetMessageBytes(message));
}
return payloads;
}
I removed that package as we are not using it.
Does that mean you're getting a reference to "Microsoft.AspNetCore.SignalR.Core" from "Microsoft.Azure.SignalR"?
What runtime are you using? dotnet --info
We do not have that package installed and not referencing it in code. I must have added it accidentally while troubleshooting at one point.
csproj
<PropertyGroup>
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
<DebugType>Full</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Adyen.EcommLibrary" Version="2.1.0" />
<PackageReference Include="Lamar" Version="3.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0-preview9.19417.2" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="3.0.0-preview9.19417.2" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.0.0-preview9.19417.2" />
<PackageReference Include="Microsoft.Azure.SignalR" Version="1.1.0-preview1-10442" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.8.0-beta1" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.11.0-beta1" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0-preview9.19417.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview9.19417.1" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.0" />
<PackageReference Include="Moq.AutoMock" Version="1.2.0.122-pre" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
dotnet --info
Runtime Environment:
OS Name: Windows
OS Version: 10.0.18362
OS Platform: Windows
RID: win10-x86
Base Path: C:\Program Files (x86)\dotnet\sdk\3.0.100-preview8-013656\
Host (useful for support):
Version: 3.0.0-preview8-28405-07
Commit: d01b2fb7bc
.NET Core SDKs installed:
2.2.300 [C:\Program Files (x86)\dotnet\sdk]
3.0.100-preview8-013656 [C:\Program Files (x86)\dotnet\sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.2.5 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.2.5 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-preview8.19405.7 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.2.5 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview8-28405-07 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0-preview8-28405-07 [C:\Program Files (x86)\dotnet\shared\Microsoft.WindowsDesktop.App]
Looked into this. Thanks for pointing out https://github.com/Azure/azure-signalr/blob/dev/src/Microsoft.Azure.SignalR/HubHost/ServiceLifetimeManagerBase.cs#L221!
This will be fixed in preview9 via https://github.com/aspnet/AspNetCore/pull/13261
Great, thanks for the quick fix!
Could someone please clarify if we should do anything else but adding AddNewtonsoftJsonProtocol to make things working "same way" as it was on 2.2?
After we have migrated to the 3.1 we observe few weird behaviours so wondering if we did something wrong.
Here is the startup.cs
/*
* TODO: Move to the System.Text.Json serialization
*/
var signalRServiceBuilder = services.AddSignalR().AddNewtonsoftJsonProtocol(o =>
{
o.PayloadSerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
o.PayloadSerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
o.PayloadSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
});
if (IsScaleOutEnabled)
{
signalRServiceBuilder
.AddAzureSignalR();
}
@yahorsi Please file a new issue. This sounds like a different question.
Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.
This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue!
Most helpful comment
I am using https://github.com/dotnet/corefx/issues/36510 to track cyclic references.
You will need to add a reference to "Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" starting in preview5 if you want to continue using Newtonsoft.Json.