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

如何获取正确JSON格式流并通过System.Text.Json反序列化实体类?

问题:请求API返回HTML而非JSON,无法反序列化为League实体类

尝试将API响应流转换为League实体类时,始终收到HTML格式的内容而非JSON,清理浏览器缓存也无法解决。通过string res = await httpResponseMessage.Content.ReadAsStringAsync();确认返回内容是HTML,导致反序列化异常,需要获取JSON格式响应来完成反序列化和数据库存储。

控制器代码

using Microsoft.AspNetCore.Mvc;
using Model;
using System.Text.Json;

namespace Web.Controllers.HttpControllers
{
    public class LeagueClientController : ControllerBase
    {
        private readonly Uri _leagueRequest;
        private readonly BetDBContext _dbContext;
        private readonly HttpClient _httpClient;

        public LeagueClientController(IHttpClientFactory factory, BetDBContext dbContext)
        {
            _leagueRequest = new Uri("https://www.api-football.com/leagues");
            _dbContext = dbContext;
            _httpClient = factory.CreateClient("BetHttpClient");
        }

        [HttpGet]
        [Route("[controller]")]
        public async Task<League> GetLeagues()
        { 
            try
            {
                var leagueResponse = await _httpClient.GetAsync(_leagueRequest)??throw new NullReferenceException();
                if (leagueResponse.IsSuccessStatusCode)
                {
                    Stream stream = await leagueResponse.Content.ReadAsStreamAsync();
                    if (stream != null)
                    {
                        var league = await JsonSerializer.DeserializeAsync<League>(stream)??throw new ArgumentNullException();
                        await _dbContext.AddAsync(league);
                        await _dbContext.SaveChangesAsync();
                    }
                }
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine($"{e.Message} - can not connect to remote source");
            }
            return new League();  
        }
    }
}

HttpClient配置代码

builder.Services.AddHttpClient("BetHttpClient", httpClient =>
{
    httpClient.BaseAddress = new Uri("https://v3.football.api-sports.io/");
    httpClient.DefaultRequestHeaders.Add("x-apisports-key", "it is secret");
    httpClient.DefaultRequestHeaders.Add("x-rapidapi-host", "v3.football.api-sports.io");
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
});

解决方案

1. 修正API请求地址

当前使用的https://www.api-football.com/leagues是旧版官网地址,并非实际API端点。结合HttpClient配置的BaseAddresshttps://v3.football.api-sports.io/,正确的联赛API端点应为相对路径/leagues。修改控制器中的请求地址:

// 替换原完整URI,改用相对路径
_leagueRequest = new Uri("/leagues", UriKind.Relative);
// 或者直接在GetAsync中传入相对路径
var leagueResponse = await _httpClient.GetAsync("/leagues") ?? throw new NullReferenceException();

2. 排查响应错误细节

HTML响应通常对应4xx/5xx错误(如404未找到、401未授权),建议在代码中打印状态码和响应内容,定位具体问题:

var leagueResponse = await _httpClient.GetAsync("/leagues");
Console.WriteLine($"Status Code: {leagueResponse.StatusCode}");
var responseContent = await leagueResponse.Content.ReadAsStringAsync();
Console.WriteLine($"Response Content: {responseContent}");

if (leagueResponse.IsSuccessStatusCode)
{
    // 原反序列化逻辑
}
else
{
    Console.WriteLine($"Request failed with status code: {leagueResponse.StatusCode}");
}

3. 验证API密钥有效性

确认x-apisports-key的密钥是否有效,过期或无效的密钥会导致API返回错误HTML页面。可通过Postman等工具直接测试API端点,验证密钥能否正常返回JSON。

4. 移除冗余请求头

x-rapidapi-host头在api-sports.io V3版本中无需配置,移除该头避免请求异常:

// 删除此行配置
// httpClient.DefaultRequestHeaders.Add("x-rapidapi-host", "v3.football.api-sports.io");

内容的提问来源于stack exchange,提问作者Maciej Ambroziak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 21:25:14