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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:30:01