Blazor Server与Angular集成自定义元素失败,求解决方案
在Angular + ASP.NET Core项目中集成Blazor Server自定义元素失败的解决方案
问题背景
使用Angular + ASP.NET Core项目模板,在Blazor Server环境中集成Blazor自定义元素,已完成组件创建、自定义元素注册、Angular代理配置等设置,但运行时自定义元素无法工作,出现WebSocket连接失败错误。
错误信息

[webpack-dev-server] Live Reloading enabled. blazor.server.js:1 WebSocket connection to 'wss://localhost:44476/_blazor?id=gxW6SsA09YwNC2qyxoqguw' failed: (anonymous) @ blazor.server.js:1 blazor.server.js:1 [2023-01-13T18:51:43.964Z] Information: (WebSockets transport) There was an error with the transport. blazor.server.js:1 [2023-01-13T18:51:43.967Z] Error: Failed to start the transport 'WebSockets': Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.
示例代码仓库:NavinVinayagam/AngularWithCore
已配置的代码细节
- 项目文件添加NuGet包
<ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Components.CustomElements" Version="7.0.2" /> <PackageReference Include="Microsoft.AspNetCore.SpaProxy" Version="7.0.1" /> </ItemGroup>
- 创建Counter.razor组件(路径:AngularWithCore/Pages/Counter.razor)
<h1>@Title</h1> <p role="status">Current count: @currentCount</p> <p>Increment amount: @IncrementAmount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private DateTime date = DateTime.Today; [Parameter] public string Title { get; set; } = "Blazor Counter"; [Parameter] public int? IncrementAmount { get; set; } private void IncrementCount() { currentCount += IncrementAmount.GetValueOrDefault(1); } }
- Program.cs配置
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(options => { options.RootComponents.RegisterCustomElement<Counter>("my-blazor-counter"); }); var app = builder.Build(); app.MapBlazorHub();
- Angular代理配置
const target = env.ASPNETCORE_HTTPS_PORT ? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}` : env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:6937'; const PROXY_CONFIG = [ { context: [ "/weatherforecast", "/_content", "/_framework", "/_blazor" ], target: target, secure: false, ws: true, logLevel: "debug", headers: { Connection: 'Keep-Alive' } } ] module.exports = PROXY_CONFIG;
- Angular Index.html添加Blazor脚本
<head> <meta charset="utf-8" /> <title>AngularWithCore</title> <base href="/" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" type="image/x-icon" href="favicon.ico" /> <script src="_content/Microsoft.AspNetCore.Components.CustomElements/Microsoft.AspNetCore.Components.CustomElements.lib.module.js"></script> <script src="_framework/blazor.server.js"></script> </head>
- Angular页面添加自定义元素
<h1>Blazor Counter </h1> <my-blazor-counter increment-amount=4></my-blazor-counter>
解决步骤
1. 修复Program.cs中间件顺序
Blazor Server中间件需按正确顺序加载,确保静态文件、路由等中间件在MapBlazorHub之前配置,修改Program.cs:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(options => { options.RootComponents.RegisterCustomElement<Counter>("my-blazor-counter"); }); var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.MapControllers(); app.MapBlazorHub(); app.MapFallbackToFile("index.html"); app.Run();
2. 调整Blazor脚本加载逻辑
修改blazor.server.js的加载方式,避免Angular初始化前触发连接,修改Index.html:
<head> <meta charset="utf-8" /> <title>AngularWithCore</title> <base href="/" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" type="image/x-icon" href="favicon.ico" /> <script src="_content/Microsoft.AspNetCore.Components.CustomElements/Microsoft.AspNetCore.Components.CustomElements.lib.module.js"></script> <script src="_framework/blazor.server.js" autostart="false"></script> <script> document.addEventListener('DOMContentLoaded', function() { Blazor.start({ configureSignalR: function (builder) { builder.withUrl('/_blazor', { skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets }); } }); }); </script> </head>
3. 验证代理端口匹配
确认代理配置中的目标端口与ASP.NET Core实际运行端口一致,可通过项目启动控制台输出查看ASP.NET Core的监听端口,调整代理配置中的target值。
4. 添加CORS配置(跨端口场景)
若Angular与ASP.NET Core运行在不同端口,在Program.cs中添加CORS策略:
builder.Services.AddCors(options => { options.AddPolicy("AllowAngular", policy => { policy.WithOrigins("http://localhost:4200") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); }); }); // 在UseRouting之后添加 app.UseCors("AllowAngular");
5. 确认组件参数绑定
自定义元素标签名my-blazor-counter需与注册名称完全一致,参数increment-amount已正确映射组件的IncrementAmount参数(Blazor自动将kebab-case转换为PascalCase),无需修改。
验证
完成以上修改后,重启ASP.NET Core和Angular项目,检查WebSocket连接状态,确认自定义元素可正常渲染并响应交互。
内容的提问来源于stack exchange,提问作者Navin Vinayagam
相关产品推荐
相关产品推荐

