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

使用Refit 6.0.94时Linux容器中Post/Patch请求抛出System.Text.Json.JsonReaderException问题求助

问题排查与解决方案

这个问题我之前遇到过类似的情况,大概率是API返回的响应不是合法JSON导致的——错误里的'M'很可能是"Method Not Allowed"这类文本响应的开头,而Refit默认期望解析JSON格式的响应,所以抛出了解析异常。结合你的场景(本地正常、容器里只有Patch/Post出错),可以按以下步骤排查和解决:

第一步:先确认API返回的原始内容

在你的Blazor代码的catch块里,先把ApiException的原始响应内容打印出来(比如写入日志或者临时显示在页面上),这是定位问题的关键:

catch (ApiException ex)
{
    // 先记录原始响应内容
    var rawResponseContent = ex.Content;
    Console.WriteLine($"Raw API Response: {rawResponseContent}");
    
    try
    {
        var errors = await ex.GetContentAsAsync<Dictionary<string, string>>();
        var message = string.Join("; ", errors.Values);
        throw new Exception(message);
    }
    catch
    {
        // 如果解析JSON失败,直接抛出原始响应内容
        throw new Exception($"API Error: {rawResponseContent}");
    }
}

如果输出是类似Method Not Allowed的文本,那问题就出在路由不匹配或者API端点未正确接收Patch/Post请求。

第二步:检查路由匹配一致性

你的Refit接口里,Patch/Post的路由是[Patch("/CustomerCare/")]和[Post("/CustomerCare/")](末尾带斜杠),而API的Patch方法是[HttpPatch](没有指定路由)。结合BaseAddress是http://myservername/api/v1,最终的请求路径是http://myservername/api/v1/CustomerCare/。

需要确认API控制器的路由配置:比如你的CustomerCareController是不是有类似这样的路由?

[ApiController]
[Route("api/v1/[controller]")] // 这里的路由是api/v1/CustomerCare
public class CustomerCareController : ControllerBase
{
    [HttpPatch]
    public async Task<IActionResult> PatchAsync([FromBody] Customer customer)
    {
        // ...
    }
}

如果是这样,API的Patch端点路径是api/v1/CustomerCare(不带末尾斜杠),而Refit请求的是api/v1/CustomerCare/——末尾多了个斜杠会导致路由不匹配,API返回405 Method Not Allowed(文本响应),这就是你看到的'M'开头错误的来源。

解决方案:统一路由格式,去掉Refit接口里路由的末尾斜杠:

public interface ICustomerService
{
    [Delete("/CustomerCare")] // 同步修改Delete的路由,保持一致性
    Task<bool> DeleteCustomer(int id);
    [Patch("/CustomerCare")]
    Task<bool> PatchCustomerAsync([Body] Customer customer);
    [Get("/CustomerCare/{id}")]
    Task<Customer> GetCustomerByIdAsync(int id);
    [Post("/CustomerCare")]
    Task PostAsync([Body] Customer customer);
}

第三步:确保API错误响应也是JSON格式

如果API在出现异常时返回的是HTML错误页面(比如默认的ASP.NET错误页),也会导致Refit解析JSON失败。建议给API配置全局异常处理,确保所有错误都返回JSON格式:

// 在API的Startup.cs/Program.cs中添加全局异常处理中间件
app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        context.Response.ContentType = "application/json";
        var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
        var exception = exceptionHandlerPathFeature.Error;
        
        var errorResponse = new { Message = exception.Message, StatusCode = StatusCodes.Status500InternalServerError };
        await context.Response.WriteAsJsonAsync(errorResponse);
    });
});

第四步:验证Refit的序列化配置(可选)

虽然本地正常,但可以显式指定Refit使用System.Text.Json序列化,确保容器环境下的一致性:

services.AddRefitClient<ICustomerService>(new RefitSettings
{
    ContentSerializer = new SystemTextJsonContentSerializer(new JsonSerializerOptions
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        // 匹配你的POCO类配置,比如支持可空DateTime
        Converters = { new JsonStringEnumConverter() }
    })
}).ConfigureHttpClient(c => c.BaseAddress = new Uri("http://myservername/api/v1"));

按以上步骤排查,大概率能解决你的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:17:36