首页 > 解决方案 > 在 WPF 核心 Windows 应用程序中使用SignalR

问题描述

尝试使用 .NET Core 3.0 在 WPF Windows 应用程序中设置 SignalR 服务器。我能找到的所有示例都假设有一个带有 Configure() 方法的 startup.cs,我可以在其中调用 UseSignalR。但我没有。我有一个“App”类,派生自 Application。(我可能遗漏了与 SignalR 无关的有关 WPF/Core/Win 的基本知识)

代码摘录:

public partial class App : Application
{
    public IServiceProvider ServiceProvider { get; private set; }

    public IConfiguration Configuration { get; private set; }

    protected override void OnStartup(StartupEventArgs e)
    {
        var builder = new ConfigurationBuilder()
         .SetBasePath(Directory.GetCurrentDirectory())
         .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

        Configuration = builder.Build();

        var serviceCollection = new ServiceCollection();
        ConfigureServices(serviceCollection);

        ServiceProvider = serviceCollection.BuildServiceProvider();

        var mainWindow = ServiceProvider.GetRequiredService<MainWindow>();
        mainWindow.Show();
    }

    private void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient(typeof(MainWindow));

        services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
        {
            builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader();
        }));

        services.AddSignalR().AddHubOptions<TestHub>(options =>
        {
            options.EnableDetailedErrors = true;
        });
    }

到目前为止一切都很好,因为它至少可以编译和运行,如果还没有做任何有形的事情的话。

我相信我现在需要实际配置集线器:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseSignalR((configure) =>
        {
            var desiredTransports =
                HttpTransportType.WebSockets |
                HttpTransportType.LongPolling;

            configure.MapHub<TestHub>("/testhub", (options) =>
            {
                options.Transports = desiredTransports;
            });
        });
    }

但是这个方法永远不会被调用——我不相信它应该来自应用程序,而是来自 StartUp。

最后,我的中心类:

class TestHub : Hub
{
    public Task SendMessage(string user, string message)
    {
        return Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

编译正常,但我认为集线器实际上并没有运行,所以它当然什么也不做。

在这种类型的设置中,为了让集线器启动和正确配置,我应该做些什么不同的事情吗?

FWIW 我在标准 .NET 框架(不是 Core)中使用 SignalR 和 WinForms 应用程序没有问题,所以我对这些概念有点熟悉,只是不熟悉 Core/WPF/Win 方式。

非常感谢。

标签: c#wpf.net-coresignalr

解决方案


构建托管 ASP.NET Core 的 WPF 应用程序的步骤:

创建解决方案:

dotnet new sln WpfHostingAspNetCore -o WpfHostingAspNetCore
cd WpfHostingAspNetCore

创建项目:

dotnet new wpf -o src/WpfHostingAspNetCore.WpfApplication
dotnet new web -o src/WpfHostingAspNetCore.WebApplication
dotnet sln add src/*

添加项目引用:

cd src/WpfHostingAspNetCore.WpfApplication
dotnet add reference ../WpfHostingAspNetCore.WebApplication

添加框架引用:

编辑WpfHostingAspNetCore.WpfApplication.csproj以下行并将其插入到ItemGroup元素中:

<FrameworkReference Include="Microsoft.AspNetCore.App"/>

在 WPF 应用程序生命周期内托管 ASP.NET Core

App.xaml.cs

public partial class App : Application
{
    private IHost _host;

    protected override void OnStartup(StartupEventArgs e)
    {
        _host = Host.CreateDefaultBuilder(e.Args)
            .ConfigureWebHostDefaults(webHostBuilder => webHostBuilder.UseStartup<WebApplication.Startup>())
            .ConfigureServices(services =>
            {
                services.AddTransient<MainWindow>();
            })
            .Build();

        _host.Start();

        _host.Services.GetRequiredService<MainWindow>().Show();
    }

    protected override void OnExit(ExitEventArgs e) => _host.Dispose();
}

运行并测试托管在 WPF 应用程序上的简单 Web 应用程序

dotnet run

如果它工作正常,您将在http://localhost/上看到“Hello world”

然后在 Web 应用程序项目的 Startup 类中添加您的 SignalR 服务和中间件。


推荐阅读