如何解决Blazor无法接收在服务器端创建的信号器 演示应用
下面有许多教程,示例,我在服务器端调用下面的示例,但是客户端却没有收到,有时它可以工作,但有时却不起作用(更多的是不起作用的)
本来应该很简单,但事实并非如此,任何建议都会对我有很大帮助!
服务器端
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();
});
}
}
我在哪里使用信号器
await _novoPedidoContext.Clients.All.SendAsync("NovoPedido",ListaComandaItem);
客户端-Blazor
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");
});
}
}
我在哪里打电话..
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();
}
解决方法
您没有在标签中指定是客户端(WASM)还是服务器端Blazor。
看着我在ConfigureServices
中注意到这一行的问题:
services.AddServerSideBlazor();
因此,您尝试使用SignalR,这是服务器中的客户端通信库。在服务器端Blazor 所有C#代码都在服务器上运行。在这方面,SignalR是多余的,因为Blazor已经使用它来在客户端和服务器之间进行通信。
通过一个非常幸运的巧合,我实际上写了一个应用程序来对此进行测试。我创建了服务器端Blazor应用,并编写了此服务:
public class TalkService
{
public TalkService()
{
history = new List<string>();
}
public Action<string> OnChange { get; set; }
// inform all users of new message
public Task SendAsync(string message)
{
// add to history
history.Add(message);
// ensure only last 10 shown
if (history.Count > 10) history.RemoveAt(0);
OnChange.Invoke(message);
return Task.FromResult(0);
}
private readonly List<string> history;
public IReadOnlyList<string> GetHistory() => history;
}
然后我在服务器上将其注册为 Singleton (所有客户端都使用相同的服务)
在Startup.cs
方法的ConfigureServices()
中:
services.AddSingleton<TalkService>();
然后按如下方式重写Index.razor
:
@page "/"
@inject TalkService service
<p>Talk App started</p>
<p>Send a message: <input type="text"@bind="@message" />
<button class="btn btn-sm btn-primary" @onclick="Send" >Send</button>
</p>
@foreach (var m in messages)
{
<p>@m</p>
}
@code {
string message;
async Task Send()
{
if(!string.IsNullOrWhiteSpace(message))
await service.SendAsync(message);
message = string.Empty;
}
List<string> messages;
protected override void OnParametersSet()
{
// load history
messages = service.GetHistory().ToList();
// register for updates
service.OnChange += ChangeHandler;
}
protected void ChangeHandler(string message)
{
messages.Add(message);
InvokeAsync(StateHasChanged);
}
}
对话服务当然是一个基本的“聊天”示例。这是一个Singleton,因此引用它的所有页面/客户端都使用相同的实例。该服务具有一个简单的事件OnChange
,客户端(如“索引”页面)可以在其他地方监听更改。
此应用程序不需要SignalR,因为它已经在服务器端存在了。
演示应用
该演示应用程序还具有后台服务,该服务还可以生成时间消息。我将其推送到GitHub作为指导:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。