Azure静态Web应用中Blazor WASM调用托管Function API遭连接拒绝
Blazor WASM部署Azure静态Web应用后API调用失败问题排查与解决
问题现象
将Blazor WASM应用部署至Azure静态Web应用,搭配托管的.NET 8独立进程Azure Function API:
- Postman通过Web应用URL+API路由直接调用API,能正常获取响应,Application Insights有对应日志;
- 部署后的WASM应用内调用同一端点时,浏览器控制台抛出
net::ERR_CONNECTION_REFUSED错误,Application Insights无请求记录; - 本地运行时一切正常。
相关配置与代码
Blazor WASM的appsettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ApiBase": "http://localhost:7071" }
Azure Function的launchSettings.json
{ "profiles": { "Project.Api": { "commandName": "Project", "commandLineArgs": "--port 7071", "launchBrowser": false } } }
HttpClient注册代码
var apiBase = builder.Configuration["ApiBase"] ?? throw new ArgumentException("API base address not found in config."); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(apiBase) });
API调用代码
var response = await HttpClient.PostAsJsonAsync("/api/send-contact-email", sendEmailRequest);
Azure Function核心代码
public class SendContactEmailFunction(ILoggerFactory loggerFactory, ISender sender) { private readonly ILogger logger = loggerFactory.CreateLogger<SendContactEmailFunction>(); [Function(nameof(SendContactEmailFunction))] public async Task<HttpResponseData> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = "send-contact-email")] HttpRequestData req, FunctionContext executionContext, CancellationToken cancellationToken) { logger.LogInformation($"{nameof(SendContactEmailFunction)} function received a request."); var requestBody = await new StreamReader(req.Body).ReadToEndAsync(cancellationToken); var request = JsonConvert.DeserializeObject<SendContactEmailRequest>(requestBody); HttpResponseData response; try { if (request == null) { throw new ApplicationException("Unable to deserialize response."); } var emailCommand = new SendContactEmailCommand( request.Name, request.FromEmail, request.Message, request.RecaptchaResponse); var sendEmailResult = await sender.Send(emailCommand, cancellationToken); if (sendEmailResult.IsFailure) { logger.LogError("Send email command failed. Error: {Error}", sendEmailResult.Error.Message); response = req.CreateResponse(HttpStatusCode.BadRequest); var error = new ErrorResponse { Code = (int)HttpStatusCode.BadRequest, Message = sendEmailResult.Error.Message }; await response.WriteAsJsonAsync(error, cancellationToken); } else { response = req.CreateResponse(HttpStatusCode.OK); await response.WriteAsJsonAsync("", cancellationToken: cancellationToken); } } catch (Exception e) { logger.LogError(e, "Exception occured. Error: '{Message}'", e.Message); response = req.CreateResponse(HttpStatusCode.InternalServerError); await response.WriteAsJsonAsync(ErrorResponse.Generic, cancellationToken); } return response; } }
问题根源
部署后的WASM应用仍沿用本地开发环境的API地址http://localhost:7071。由于WASM运行在用户浏览器中,浏览器会尝试向用户本地的7071端口发起请求,而用户本地并没有部署该API服务,因此触发连接拒绝错误。
解决步骤
1. 配置环境专属API地址
在Blazor WASM项目中添加环境特定配置文件:
- 开发环境:保留
appsettings.Development.json中的"ApiBase": "http://localhost:7071",适配本地调试; - 生产环境:创建
appsettings.Production.json,配置为Azure静态Web应用的API相对路径:
{ "ApiBase": "/api" }
2. 利用Azure静态Web应用同域路由特性
Azure静态Web应用会自动将/api前缀的请求转发至托管的Azure Function,前端使用相对路径/api作为API基础地址,既避免跨域问题,又无需硬编码具体域名,适配部署环境。
3. 确保部署时加载生产配置
- 确认Azure静态Web应用的构建流程会自动加载
appsettings.Production.json; - 也可在Azure门户的静态Web应用 -> 配置 -> 应用程序设置中添加
ApiBase配置项,值设为/api,覆盖本地配置。
4. 优化API调用路径(可选)
若BaseAddress设为/api,调用代码可简化路径,避免重复前缀:
var response = await HttpClient.PostAsJsonAsync("/send-contact-email", sendEmailRequest);
(拼接后路径为/api/send-contact-email,与Function的Route配置完全匹配)
内容的提问来源于stack exchange,提问作者Beau
相关产品推荐
相关产品推荐

