如何在Blazor中调用Web API 基于现有Console加密货币接口代码适配
问题核心故障原因
- 过时类使用:
WebClient已被官方标记为过时,且Blazor环境下同步请求方法会阻塞UI线程,WebAssembly模式下甚至会直接抛出运行时异常,Blazor官方推荐使用依赖注入的HttpClient发起异步请求 - 跨域限制:CoinMarketCap公开接口默认未开放浏览器端跨域请求权限,Blazor WebAssembly直接前端请求会被CORS策略拦截,推荐使用Blazor Server在服务端发起请求,或自行搭建后端代理转发请求
- 方法调用逻辑混乱:自定义
Request方法为同步实现,却在异步方法GetCryptoList中混用,线程调度逻辑错误 - JSON结构不匹配:CoinMarketCap返回的加密货币列表并非根级数组,而是包裹在
data字段中,且price属性嵌套在quote.USD.price路径下,原实体类结构完全无法匹配返回值,会导致序列化失败 - 明文密钥风险:前端直接写死API密钥会导致密钥泄露,存在被盗刷的风险
修正后适配Blazor Server的实现代码
第一步:注册HttpClient服务
在Program.cs中添加服务注册:
builder.Services.AddHttpClient<CoinMarketCapAPI>(client => { client.BaseAddress = new Uri("https://pro-api.coinmarketcap.com/v1/"); client.DefaultRequestHeaders.Add("X-CMC_PRO_API_KEY", "你的API密钥"); client.DefaultRequestHeaders.Add("Accept", "application/json"); });
第二步:重构API类
using System.Collections.Generic; using System.Net.Http.Json; using System.Threading.Tasks; namespace Cryptonite.API { public class CoinMarketCapAPI : ReadAPI { private readonly HttpClient _httpClient; public CoinMarketCapAPI(HttpClient httpClient) { _httpClient = httpClient; } public bool IsSupported(string symbol) { throw new System.NotImplementedException(); } public override async Task<string> Request(string tail) { var query = "?start=1&limit=5000&convert=USD"; var response = await _httpClient.GetAsync($"{tail}{query}"); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } // 匹配CoinMarketCap返回结构的实体类 public class CmcResponse { public List<CryptoItem> data { get; set; } } public class CryptoItem { public string name { get; set; } public Quote quote { get; set; } } public class Quote { public USD USD { get; set; } } public class USD { public decimal price { get; set; } } public async Task<List<CryptoItem>> GetCryptoList() { var response = await _httpClient.GetFromJsonAsync<CmcResponse>("cryptocurrency/listings/latest?start=1&limit=5000&convert=USD"); return response?.data ?? new List<CryptoItem>(); } } }
第三步:Blazor页面调用示例
@inject Cryptonite.API.CoinMarketCapAPI CmcApi @page "/crypto" <h3>加密货币列表</h3> @if (CryptoList == null) { <p>加载中...</p> } else { <ul> @foreach (var item in CryptoList) { <li>@item.name : @item.quote.USD.price.ToString("C2")</li> } </ul> } @code { private List<Cryptonite.API.CoinMarketCapAPI.CryptoItem> CryptoList; protected override async Task OnInitializedAsync() { CryptoList = await CmcApi.GetCryptoList(); } }
内容的提问来源于stack exchange,提问作者karinev
相关产品推荐
相关产品推荐

