Blazor调用Web API遇“找不到主机”错误,求排查方案
Blazor WebAssembly调用API出现"No such host is known"错误排查与解决
在Blazor服务器项目中添加Web API控制器后,直接通过浏览器访问https://api.localhost:7239/api/Values/可正常返回结果,但Blazor客户端使用HttpClient调用时抛出错误:
HttpRequestException: No such host is known
复现步骤
- 创建带Interactive WebAssembly渲染模式的新Blazor应用
- 在服务器端添加
ValuesController控制器:
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { [HttpGet("")] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] public IActionResult Get() { return Ok("Now is the time for all good men to come to the aid of the party."); } }
- 服务器端Program.cs配置路由:
public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorComponents() .AddInteractiveWebAssemblyComponents(); builder.Services.AddControllers(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseWebAssemblyDebugging(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAntiforgery(); app.UseStaticFiles(); app.MapWhen( (HttpContext context) => context.Request.Host.Host.StartsWith("api"), (IApplicationBuilder configuration) => { configuration.UseRouting(); configuration.UseEndpoints(cfg => cfg.MapControllers()); } ); app.MapRazorComponents<App>() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(Client._Imports).Assembly); app.Run(); }
- 浏览器访问
https://api.localhost:7239/api/Values/确认API正常 - 客户端创建
IValuesService及实现:
public interface IValuesService { Task<string> GetAsync(); } public class ValuesService : IValuesService { private readonly HttpClient _HttpClient; public ValuesService(HttpClient httpClient) { _HttpClient = httpClient; } public async Task<string> GetAsync() { HttpResponseMessage rx = await _HttpClient.GetAsync("api/Values"); return await rx.Content.ReadAsStringAsync(); } }
- 客户端和服务器端DI注册:
builder.Services.AddSingleton<HttpClient>((IServiceProvider services) => new HttpClient() { BaseAddress = new Uri("https://api.localhost:7239") }); builder.Services.AddScoped<IValuesService, ValuesService>();
- 客户端创建
/values页面:
@page "/values" @rendermode InteractiveWebAssembly @inject IValuesService ValuesService @code { string Value { get; set; } protected override async Task OnParametersSetAsync() { try { Value = await ValuesService.GetAsync(); } catch { // 捕获到:System.Net.Http.HttpRequestException: 'No such host is known. (api.localhost:7239)' } await base.OnParametersSetAsync(); } } <PageTitle>Values service</PageTitle> <h1>Values service</h1>
- 运行应用后访问
/values页面,触发catch块
原因分析
- 客户端HttpClient注册错误:Blazor WebAssembly运行在浏览器环境中,手动实例化HttpClient并硬编码
api.localhost地址时,浏览器无法自动将该子域名解析到本地(系统默认hosts文件无此映射),导致主机查找失败。 - 服务器端路由匹配限制:服务器端通过
MapWhen仅对主机以api开头的请求映射控制器,若客户端从主域名发起请求,即使路径正确也无法命中API路由(不过本次问题核心是host解析)。 - 本地DNS映射缺失:
api.localhost并非默认本地域名,浏览器无法自动将其指向127.0.0.1或::1,导致请求无法送达本地服务器。
解决方法
方法一:修正HttpClient注册,使用相对路径(推荐)
Blazor WebAssembly框架提供的HttpClient可自动使用应用基地址,无需硬编码。修改客户端DI注册:
// 替换原有的HttpClient和服务注册代码 builder.Services.AddHttpClient<IValuesService, ValuesService>(client => { client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress); });
同时修改服务器端路由配置,移除MapWhen的限制,直接映射控制器:
// 替换原有的MapWhen代码 app.MapControllers();
此方案让客户端向当前应用主机发起API请求,避免子域名解析问题,同时服务器端所有符合控制器路由的请求都会被正确处理。
方法二:添加本地hosts映射(保留子域名场景)
若必须使用api.localhost子域名,需修改系统hosts文件:
- Windows路径:
C:\Windows\System32\drivers\etc\hosts - macOS/Linux路径:
/etc/hosts
添加以下内容:
127.0.0.1 api.localhost ::1 api.localhost
修改后客户端可正常解析api.localhost地址,结合原有的服务器端MapWhen配置即可正常调用API。
额外注意事项
- Blazor WebAssembly运行在浏览器中,请求受同源策略限制,若使用不同子域名需在服务器端配置CORS。
- 避免在Blazor WebAssembly中手动实例化HttpClient,推荐使用
AddHttpClient扩展方法,框架会处理底层请求逻辑与配置。
内容的提问来源于stack exchange,提问作者Richard Barraclough
相关产品推荐
相关产品推荐

