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

Blazor WebAssembly中GetAsync调用失败及CORS问题求助

从WinForms转Blazor WASM调用WCF API的CORS问题

我从Windows Forms转做Blazor WebAssembly开发,尝试调用一个已确认可正常向其他应用提供数据的WCF API获取数据。最初在页面加载的OnInitializedAsync方法中调用httpClient.GetAsync时直接崩溃,跟着教程改用IHttpClientFactory更新代码后,现在浏览器报CORS错误:请求被CORS策略阻止,目标资源不存在Access-Control-Allow-Origin头。这个API是十年前开发的WCF服务,想咨询实现CORS的最佳方式,是否需要重写API?


初始服务类代码

public class RecipeService : IRecipeService
{
    private readonly HttpClient httpClient;

    private string baseURL = clConstants.SERVER_PATH;
    private string apiEndPoint = "getRecipeByID/";

    public RecipeService(HttpClient httpClient)
    {
        this.httpClient = httpClient;
    }

    async Task<List<clRecipe>> IRecipeService.getRecipeByID(int id)
    {
        ConfigureHTTPClient();

        string URL = clConstants.SERVER_PATH + apiEndPoint + id.ToString();

        // 此行代码崩溃
        var res = httpClient.GetAsync(URL).Result; 
    }
}

更新后服务类及接口代码

public class RecipeService : IRecipeService
{
    private readonly string apiEndPoint = "GetRecipeByID/";

    private readonly IHttpClientFactory httpClientFactory;
    private HttpClient CreateHttpClient() => httpClientFactory.CreateClient("MainApi");

    private readonly JsonSerializerOptions jsonOptions = new()
    {
        PropertyNameCaseInsensitive = true
    };

    public RecipeService(IHttpClientFactory httpClientFactory)
    {
        this.httpClientFactory = httpClientFactory;
    }

    public async Task<List<clRecipe>>getRecipeByID(int id)
    {
        string URL = apiEndPoint + id.ToString();

        var response = await CreateHttpClient().GetAsync(URL, HttpCompletionOption.ResponseHeadersRead);
        var result = await response.Content.ReadAsStreamAsync();

        var recipe = await JsonSerializer.DeserializeAsync<List<clRecipe>>(result, jsonOptions);
        return recipe;
    }
}

public interface IRecipeService
{
    Task<List<clRecipe>> getRecipeByID(int id);
}

Program.cs配置

builder.Services.AddHttpClient("MainApi", options =>
{
     options.BaseAddress = new Uri(clConstants.SERVER_PATH);
});

builder.Services.AddSingleton<IRecipeService, RecipeService>();

页面代码

@inject IRecipeService RecipeService

private List<clRecipe> recipe { get; set; }

public interface IRecipeService
{
    Task<List<clRecipe>> getRecipeByID(int id);
}

当前错误信息

请求被CORS策略阻止:请求的资源上不存在'Access-Control-Allow-Origin'头。如果不需要获取响应内容,可将请求模式设置为'no-cors'以禁用CORS获取资源。


解决方案:无需重写API的CORS实现方式

1. 在WCF服务端直接配置CORS

对于WCF服务,有两种可靠的添加CORS支持的方式:

  • 自定义MessageInspector拦截响应:实现IDispatchMessageInspector接口,在返回响应时注入CORS头:
public class CorsMessageInspector : IDispatchMessageInspector
{
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        return null;
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        var httpResponse = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
        if (httpResponse != null)
        {
            // 生产环境建议替换为具体允许的域名,不要用*
            httpResponse.Headers.Add("Access-Control-Allow-Origin", "*"); 
            httpResponse.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
            httpResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
        }
    }
}

之后在WCF的配置文件或代码中注册该Inspector即可生效。

  • IIS托管下添加HTTP模块:如果WCF部署在IIS上,可在web.config中添加自定义HTTP模块,全局注入CORS头:
<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="CorsModule" type="YourNamespace.CorsHttpModule"/>
  </modules>
</system.webServer>

实现IHttpModule接口,在请求处理环节添加CORS头。

2. 使用反向代理(推荐生产环境)

如果不想修改WCF服务的代码或配置,可通过反向代理规避跨域问题:

  • Blazor Hosted模式集成Yarp反向代理:在Blazor Server项目中配置Yarp,将WCF API的请求转发到目标服务,浏览器仅与Blazor Server通信,避免跨域:
// Program.cs
builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
// appsettings.json
"ReverseProxy": {
  "Routes": {
    "wcf-route": {
      "ClusterId": "wcf-cluster",
      "Match": {
        "Path": "/wcf/{**catch-all}"
      }
    }
  },
  "Clusters": {
    "wcf-cluster": {
      "Destinations": {
        "wcf-service": {
          "Address": "http://你的WCF服务地址/"
        }
      }
    }
  }
}

之后Blazor服务中调用/wcf/GetRecipeByID/{id}即可。

  • IIS ARR反向代理:在IIS中安装Application Request Routing,配置转发规则,将Blazor域名下的特定路径转发到WCF服务,同样可解决跨域问题。

3. 开发环境临时方案

仅用于本地测试,可使用浏览器插件(如Chrome的CORS Unblock)临时禁用CORS检查,但绝对禁止用于生产环境。

结论

不需要重写WCF API,优先选择在WCF端配置CORS或使用反向代理方案,这两种方式成本远低于重写,且能稳定解决跨域问题。

内容的提问来源于stack exchange,提问作者Steven Marcus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 09:07:37