.net core Blazor未接收服务器端创建的信号器

.net core Blazor未接收服务器端创建的信号器,.net-core,websocket,signalr,blazor,signalr.client,.net Core,Websocket,Signalr,Blazor,Signalr.client,在许多教程、示例之后,下面的示例我在服务器端调用,但客户端不接收,有时有效,有时无效(比有效的多) 本来应该很简单,但事实并非如此,任何建议都会帮我大忙 服务器端 public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { ge

在许多教程、示例之后,下面的示例我在服务器端调用,但客户端不接收,有时有效,有时无效(比有效的多)

本来应该很简单,但事实并非如此,任何建议都会帮我大忙

服务器端

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers().AddNewtonsoftJson(options =>
        {
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        });

        var connection = @"data source=comandai.database.windows.net;initial catalog=HojeTaPago;persist security info=True;user id=Comandai;password=Ck@21112009;MultipleActiveResultSets=True;";
        services.AddDbContext<ComandaiContext>(options => options.UseSqlServer(connection));

        services.AddSignalR(options => options.KeepAliveInterval = TimeSpan.FromSeconds(5));

        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddResponseCompression(opts =>
        {
            opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "application/octet-stream" });
        });

        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "HojeTaPago API", Version = "v1" });
            c.AddSecurityDefinition("basic", new OpenApiSecurityScheme
            {
                Name = "Authorization",
                Type = SecuritySchemeType.Http,
                Scheme = "basic",
                In = ParameterLocation.Header,
                Description = "Basic Authorization header using the Bearer scheme."
            });

            c.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
                {
                      new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "basic"
                            }
                        },
                        new string[] {}
                }
            });
        });

        services.AddCors(options => options.AddPolicy("CorsPolicy",
        builder =>
        {
            builder.AllowAnyMethod().AllowAnyHeader()
                   .AllowCredentials();
        }));
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "HojeTaPago API V1");
            c.RoutePrefix = string.Empty;
        });

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseCors("CorsPolicy");

        app.UseAuthentication();

        app.UseAuthorization();

        app.UseMiddleware<AuthenticationMiddleware>();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHub<NovoPedidoHub>("/novopedidohub");
            endpoints.MapControllers();
        });
    }
}

客户端-Blazor

await _novoPedidoContext.Clients.All.SendAsync("NovoPedido", ListaComandaItem);
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddBlazoredLocalStorage();
        services.AddBootstrapCss();
        services.AddTransient<HubConnectionBuilder>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapBlazorHub();
            endpoints.MapFallbackToPage("/_Host");
        });
    }
}
公共类启动
{
公共启动(IConfiguration配置)
{
配置=配置;
}
公共IConfiguration配置{get;}
//此方法由运行时调用。请使用此方法将服务添加到容器中。
//有关如何配置应用程序的更多信息,请访问https://go.microsoft.com/fwlink/?LinkID=398940
public void配置服务(IServiceCollection服务)
{
services.AddRazorPages();
AddServerSideBlazor();
AddBlazoredLocalStorage();
services.AddBootstrapCss();
services.AddTransient();
}
//此方法由运行时调用。请使用此方法配置HTTP请求管道。
public void配置(IApplicationBuilder应用程序、IWebHostEnvironment环境)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
其他的
{
app.UseExceptionHandler(“/Error”);
//默认的HSTS值为30天。您可能希望在生产场景中更改此值,请参阅https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(端点=>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage(“/_主机”);
});
}
}
我打电话给

protected override async Task OnInitializedAsync()
{
    DataService dataService = new DataService();
    PedidosParaAceitar = new List<Comanda>(await dataService.BuscarComandasAbertas());

    connection = _hubConnectionBuilder.WithUrl(dataService.servidor + "novopedidohub",
        opt =>
        {
            opt.Transports = HttpTransportType.WebSockets;
            opt.SkipNegotiation = true;
        }).Build();

    connection.On<List<ComandaItem>>("NovoPedido", async lista =>
    {
        var idEstabelecimento = await localStorage.GetItemAsync<int>("IdEstabelecimento");

        if (lista.FirstOrDefault().Comanda.IdEstabelecimento == idEstabelecimento)
        {
            if (PedidosParaAceitar == null)
                PedidosParaAceitar = new List<Comanda>();

            if (PedidosParaAceitar.Count(x => x.Id == lista.FirstOrDefault().IdComanda) > 0)
                foreach (var comandaitem in lista)
                {
                    PedidosParaAceitar.FirstOrDefault(x => x.Id == lista.FirstOrDefault().IdComanda).ComandaItem.Add(comandaitem);
                }
            else
                PedidosParaAceitar.Add(await dataService.BuscarComandaAberta(lista.FirstOrDefault().IdComanda));

            StateHasChanged();
        }
    });

    await connection.StartAsync();
}
受保护的重写异步任务OnInitializedAsync()
{
DataService DataService=新的DataService();
pedidosparaacetar=新列表(等待dataService.BuscarComandasAbertas());
连接=_hubConnectionBuilder.WithUrl(dataService.servidor+“novopedidohub”,
选择=>
{
opt.Transports=HttpTransportType.WebSockets;
opt.SkipNegotiation=true;
}).Build();
connection.On(“NovoPedido”,异步lista=>
{
var idEstabelecimento=await localStorage.GetItemAsync(“idEstabelecimento”);
if(lista.FirstOrDefault().Comanda.IdEstabelecimento==IdEstabelecimento)
{
如果(PEDIDOSPALACETAR==null)
Peddosparaaceitar=新列表();
如果(peddosparaaceitar.Count(x=>x.Id==lista.FirstOrDefault().IdComanda)>0)
foreach(列表A中的var comandaitem)
{
pedidosparaacetar.FirstOrDefault(x=>x.Id==lista.FirstOrDefault().IdComanda.ComandaItem.Add(ComandaItem);
}
其他的
Add(wait dataService.BuscarComandaAberta(lista.FirstOrDefault().IdComanda));
StateHasChanged();
}
});
等待连接。StartAsync();
}

您没有在标签中指定这是客户端(WASM)还是服务器端Blazor

在查看问题时,我注意到
ConfigureServices
中有一行:

services.AddServerSideBlazor();
因此,您正试图使用signar,一个来自服务器的客户端通信库。在服务器端Blazor中,所有C代码都在服务器上运行。在这方面,signar是冗余的,因为Blazor已经使用它在客户端和服务器之间进行通信

幸运的是,我最近真的写了一个应用程序来测试这一点。我创建了一个服务器端Blazor应用程序,并编写了以下服务:

公共类通话服务
{
公共广播服务
{
历史=新列表();
}
更改{get;set;}时的公共操作
//通知所有用户新消息
公共任务SendAsync(字符串消息)
{
//载入史册
添加(消息);
//确保仅显示最后10个
如果(history.Count>10)history.RemoveAt(0);
OnChange.Invoke(消息);
返回Task.FromResult(0);
}
私有只读列表历史记录;
公共IReadOnlyList GetHistory()=>history;
}
然后我在服务器上将其注册为一个单例(所有客户端使用相同的服务) 在
Startup.cs
中的
ConfigureServices()
方法:


    services.AddSingleton<TalkService>();
聊天服务当然是一个基本的“聊天”示例。它是一个单实例,因此引用它的所有页面/客户端都使用相同的实例。该服务有一个简单的事件
OnChange
,客户机(如索引页)可以通过该事件监听其他地方的更改

此应用程序不需要SignalR,因为它在服务器端已经“存在”

演示应用程序 演示应用程序还有一个后台服务,可以生成时间信息。我将此推送到GitHub以提供帮助:


您没有在标签中指定这是客户端(WASM)还是服务器端Blazor

在查看问题时,我注意到
ConfigureServices
中有一行:

services.AddServerSideBlazor();
因此,您正试图使用signar,一个来自服务器的客户端通信库。在服务器端Blazor中,所有C代码都在服务器上运行。在这方面,signar是冗余的,因为Blazor已经使用它在客户端和服务器之间进行通信

幸运的是,我最近真的写了一个应用程序来测试这一点。我创建了一个服务器端Blazor应用程序,并编写了以下服务:

公共类通话服务
{
公共广播服务
{
历史=新列表();
}
公共行动