You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Server与Angular集成自定义元素失败,求解决方案

在Angular + ASP.NET Core项目中集成Blazor Server自定义元素失败的解决方案

问题背景

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

错误信息

Angular示例输出及错误信息

[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

已配置的代码细节

  1. 项目文件添加NuGet包
<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.Components.CustomElements" Version="7.0.2" />
  <PackageReference Include="Microsoft.AspNetCore.SpaProxy" Version="7.0.1" />
</ItemGroup>
  1. 创建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);
    }
}
  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();
  1. 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;
  1. 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>
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 21:35:28