.NET 6
.NET 8
嗨,
我想提出 SignalRTrigger 解决方案的问题。我和我的团队在 .NET6 项目中使用这种方法来触发一些异步操作。作为响应,我们返回一个自定义对象,指示操作是否成功。然而,在 .NET8 中,我们的 SignalRTrigger 函数始终在服务器响应中返回空结果,无论我们如何修复它。值得一提的是,在.NET8升级过程中,我们正在将功能迁移到隔离模式。
这是我们在 .NET6 中的服务器端代码:
[SignalRHub(path: "")]
public partial class MainHub : ServerlessHub<IMainHub>
{
...
[FunctionName(nameof(Echo))]
public async Task<SignalRHubActionRequest> Echo([SignalRTrigger()] InvocationContext invocationContext, string name, string message)
{
await Clients.Client(invocationContext.ConnectionId).Echo(name, message);
return new SignalRHubActionRequest { SignalRHubActionStatus = SignalRHubActionStatus.Accepted };
}
...
}
public class SignalRHubActionRequest
{
public string Id { get; set; }
public Status Status { get; set; }
}
public enum Status
{
Success,
Failure
}
.NET8 解决方案中此代码片段的唯一更改是 Echo 函数(在 SignalRTrigger 属性中):
[Function(nameof(Echo))]
public async Task<SignalRHubActionRequest> Echo([SignalRTrigger(nameof(MainHub), CATEGORY, nameof(Echo), "name", "message")] SignalRInvocationContext invocationContext, string name, string message)
{
await Clients.Client(invocationContext.ConnectionId).Echo(name, $"async : {message}");
return new SignalRHubActionRequest { SignalRHubActionStatus = SignalRHubActionStatus.Accepted };
}
这就是我们在 .NET6 中注册 SignalR 的方式:
builder.Services.Configure<SignalROptions>(o => {
var settings = new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
settings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
o.JsonObjectSerializer = new NewtonsoftJsonObjectSerializer(settings);
});
这是我们在.NET8中的注册:
services.AddSignalR()
.AddNewtonsoftJsonProtocol(options =>
{
options.PayloadSerializerSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
options.PayloadSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
});
这是我们的 C# SignalR 客户端代码:
await using var connection = new HubConnectionBuilder()
.WithAutomaticReconnect()
.WithUrl(uriTime, options =>
{
options.AccessTokenProvider = () => Task.FromResult(accessToken);
})
.AddNewtonsoftJsonProtocol(options =>
{
options.PayloadSerializerSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
options.PayloadSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
});
await connection.StartAsync();
var result01 = await connection.InvokeAsync<SignalRHubActionRequest>("Echo", name, message);
我们检查了请求并观察到服务器端在结果属性中返回 null,无论我们尝试发送什么内容(例如,用字符串代替 SignalRHubActionRequest 或将序列化器更改为默认序列化器或 json 序列化器)。我们通过使用 NGROK 和 Fiddler 等工具证实了这一点:
我们尝试了多种方法,其中最有希望的一种是使用 SignalROutput 属性来绑定输出: [SignalROutput(HubName = nameof(MainHub), ConnectionStringSetting = "AzureSignalRConnectionString")]
这导致了服务器端错误。当我们在使用此 SignalROutput 属性时将返回类型更改为字符串时,我们遇到了不同的错误。
最终,我们从存储库下载了最新的代码库并使用了提供的示例,特别是扩展解决方案,并遇到了相同的空结果问题。
这表明问题出在库内。我们不确定这些不同错误的原因,但根据这些示例,它似乎返回错误对象。这意味着我们也可以在结果属性中返回一个对象。我们最初认为此功能已被删除,但错误表明并非如此。
此外,文档并未表明从 SignalRTrigger 函数返回对象的功能已被删除。
对此的任何帮助将不胜感激。
谢谢
Azure 函数应用程序
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.7" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.1.4" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.3.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers" Version="1.0.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Rpc" Version="1.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="5.20.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.SignalRService" Version="1.14.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.4" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk.Analyzers" Version="1.2.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk.Generators" Version="1.3.2" />
<PackageReference Include="SignalRSwaggerGen" Version="4.7.0" />
</ItemGroup>
<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExcutionContext" />
</ItemGroup>
</Project>
客户端应用程序:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.7" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.7" />
</ItemGroup>
</Project>
https://github.com/Azure/azure-functions-dotnet-worker/tree/main/samples/Extensions/SignalR
我做了一些调查,我从他们的官方存储库中重现了这个问题,在我看来,Microsoft.Azure.Functions.Worker和System.Threading.Channels包之间存在问题。返回对象是对流序列化传递的对象的分配,但它在某处消失了。不能说这是 System.Threading.Channels 中的调用问题还是 Microsoft.Azure.Functions.Worker 中的序列化问题。