Blazor WebAssembly调用外部API时的CORS问题解决咨询
问题背景
调用https://boi.org.il/PublicApi/GetExchangeRates时触发CORS拦截,错误信息:
Access to fetch at 'https://boi.org.il/PublicApi/GetExchangeRates' from origin 'https://localhost:7246' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
所有客户端调用方式(内置Http工具、RestSharp等)、部署场景(独立WASM、托管WASM、IIS)均触发该错误,且服务器端转发方案不可用,需纯客户端解决。
客户端可行方案
1. 使用no-cors模式(仅适用于不需要读取响应内容的场景)
如果不需要获取API返回的数据,只是需要触发请求,可在请求中设置mode: 'no-cors'。但此模式下浏览器会返回不透明响应,无法读取响应内容,仅能用于缓存或其他无需数据的场景。
示例(使用内置HttpClient):
var request = new HttpRequestMessage(HttpMethod.Get, "https://boi.org.il/PublicApi/GetExchangeRates"); request.SetBrowserRequestMode(BrowserRequestMode.NoCors); var response = await _httpClient.SendAsync(request); // 注意:无法读取response.Content
2. 利用JSONP(需API支持)
如果API支持JSONP格式,可通过动态创建<script>标签绕过CORS限制。首先确认API是否接受callback参数并返回包裹在函数调用中的JSON数据。
步骤:
- 在Blazor组件中创建JS互操作方法,动态插入script标签
- 定义全局回调函数接收API返回数据
- 调用JS方法发起请求
示例:
Blazor组件代码:
@inject IJSRuntime JSRuntime <button @onclick="FetchData">获取汇率数据</button> @if (_exchangeRates != null) { <p>获取到数据:@_exchangeRates</p> } @code { private string _exchangeRates; private async Task FetchData() { // 注册回调函数 await JSRuntime.InvokeVoidAsync("registerExchangeRateCallback", DotNetObjectReference.Create(this)); // 发起JSONP请求 await JSRuntime.InvokeVoidAsync("fetchExchangeRatesWithJsonp"); } [JSInvokable] public void OnExchangeRatesReceived(string data) { _exchangeRates = data; StateHasChanged(); } }
wwwroot/js/custom.js:
window.registerExchangeRateCallback = (dotNetRef) => { window.exchangeRateCallback = (data) => { dotNetRef.invokeMethodAsync('OnExchangeRatesReceived', JSON.stringify(data)); }; }; window.fetchExchangeRatesWithJsonp = () => { const script = document.createElement('script'); // 假设API支持callback参数,替换为实际参数名 script.src = 'https://boi.org.il/PublicApi/GetExchangeRates?callback=exchangeRateCallback'; document.body.appendChild(script); // 请求完成后移除script标签 script.onload = () => script.remove(); };
注意:如果目标API不支持JSONP,此方法无效。可先在浏览器中访问带callback参数的URL,确认返回格式是否符合JSONP要求。
3. 浏览器扩展代理(仅开发环境可用)
开发阶段可使用浏览器扩展(如CORS Unblock、Allow CORS: Access-Control-Allow-Origin)临时绕过CORS限制,但此方案仅适用于开发调试,不能用于生产环境。
关键说明
由于目标API未配置Access-Control-Allow-Origin响应头,浏览器的同源策略会阻止客户端直接读取响应内容。上述方案中,仅当API支持JSONP时才能完整获取数据;no-cors模式无法读取数据;浏览器扩展仅适用于开发。
内容的提问来源于stack exchange,提问作者Yaron Amar

