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

Visual Studio 2022调用POST接口遇JObject解析错误及415状态码问题

问题排查:POST接口调用415错误导致Json解析失败

问题现象

调用POST接口时,在jsonObj = JObject.Parse(result);代码处抛出Newtonsoft.Json.JsonReaderException: "Error reading JObject from JsonReader. Path '', line 0, position 0."异常,捕获到的API响应为415 Unsupported Media Type。

接口响应信息

{StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Pragma: no-cache
X-Frame-Options: DENY
Referrer-Policy: no-referrer
Cache-Control: no-store, must-revalidate, no-cache, max-age=0
Date: Wed, 17 Jul 2024 08:47:38 GMT
Server: nginx/1.24.0
Content-Type: application/json
Expires: 0
}}

相关代码

LoginToken方法

private List<Token> LoginToken(string username, string password)
{
 string api = "";
 List<Token> list = new List<Token>();
 string url = "";
 Dictionary<string, string> dics = new Dictionary<string, string>
 {
   { "username", username },
   { "password", password },
   { "loginType", "account" },
   { "grantType", "password" }
 };
 Task<string> task = Api.InvokeWebapi(url, api, "POST", dics);
 string result = task.Result;

 if (result != null)
 {
     JObject jsonObj = null;
     jsonObj = JObject.Parse(result);
     DataInfo info = new DataInfo();
     info.statusCode = Convert.ToInt32(jsonObj["code"]);
     info.message = jsonObj["message"].ToString();
     if (info.statusCode == 1)
     {
         JArray jlist = JArray.Parse(jsonObj["data"].ToString());
         for (int i = 0; i < jlist.Count; ++i)
         {
             Token ver = new Token();
             JObject tempo = JObject.Parse(jlist[i].ToString());
             ver.access_token = tempo["access_token"].ToString();
             ver.token_type = tempo["token_type"].ToString();
             ver.expires_in = Convert.ToInt32(tempo["expires_in"]);
             ver.scope = tempo["scope"].ToString();
             ver.name = tempo["name"].ToString();
             ver.my_Corp = tempo["my_Corp-Code"].ToString();
             ver.userId = Convert.ToInt32(tempo["userId"]);
             ver.username = tempo["username"].ToString();
             ver.jti = tempo["jti"].ToString();
             list.Add(ver);
         }
     }
 }
 return list;
}

InvokeWebapi方法

public async Task<string> InvokeWebapi(string url, string api, string type, Dictionary<string, string> dics)
{
    string result = string.Empty;
    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Add("Authorization", "Basic 1111");
    client.BaseAddress = new Uri(url);

    client.Timeout = TimeSpan.FromSeconds(510);

    if (type.ToLower() == "put")
    {
        HttpResponseMessage response;
        if (dics.Keys.Contains("input"))
        {
            if (dics != null)
            {
                foreach (var item in dics.Keys)
                {
                    api = api.Replace(item, dics[item]).Replace("{", "").Replace("}", "");
                }
            }
            var contents = new StringContent(dics["input"], Encoding.UTF8, "application/json");
            response = client.PutAsync(api, contents).Result;
            if (response.IsSuccessStatusCode)
            {
                result = await response.Content.ReadAsStringAsync();
                return result;
            }
            return result;
        }

        var content = new FormUrlEncodedContent(dics);
        response = client.PutAsync(api, content).Result;
        if (response.IsSuccessStatusCode)
        {
            result = await response.Content.ReadAsStringAsync();
            return result;
        }
    }
    else if (type.ToLower() == "post")
    {
        var content = new FormUrlEncodedContent(dics);

        HttpResponseMessage response = client.PostAsync(api, content).Result;
        if (response.IsSuccessStatusCode)
        {
            result = await response.Content.ReadAsStringAsync();
            return result;
        }
    }
    else if (type.ToLower() == "get")
    {
        HttpResponseMessage response = client.GetAsync(api).Result;

        if (response.IsSuccessStatusCode)
        {
            result = await response.Content.ReadAsStringAsync();
            return result;
        }
    }
    else
    {
        return result;
    }
    return result;
}

原因分析

  1. 415错误根源:当前POST请求使用FormUrlEncodedContent发送数据,请求头Content-Type为application/x-www-form-urlencoded,但目标API仅支持application/json格式的请求体,服务器因此返回415不支持的媒体类型错误。
  2. Json解析失败:请求返回错误时,InvokeWebapi方法未读取错误响应内容,直接返回空字符串。后续调用JObject.Parse(result)时,传入空字符串触发JsonReaderException。

解决方法

1. 修改POST请求的内容格式

将POST请求的FormUrlEncodedContent替换为StringContent,以JSON格式发送数据并设置正确的Content-Type:

else if (type.ToLower() == "post")
{
    // 将字典序列化为JSON字符串
    string jsonBody = JsonConvert.SerializeObject(dics);
    var content = new StringContent(jsonBody, Encoding.UTF8, "application/json");

    HttpResponseMessage response = await client.PostAsync(api, content);
    // 无论响应是否成功,都读取响应内容
    result = await response.Content.ReadAsStringAsync();
    if (response.IsSuccessStatusCode)
    {
        return result;
    }
    // 错误时返回响应内容,便于上层处理
    return result;
}

2. 统一处理响应内容

修改InvokeWebapi方法,所有请求分支都读取响应内容,避免空字符串导致解析错误:

// 以GET分支为例,其他分支同理
else if (type.ToLower() == "get")
{
    HttpResponseMessage response = await client.GetAsync(api);
    result = await response.Content.ReadAsStringAsync();
    if (response.IsSuccessStatusCode)
    {
        return result;
    }
    return result;
}

3. 优化异步调用方式

避免使用.Result阻塞线程,将LoginToken改为异步方法并使用await调用:

private async Task<List<Token>> LoginToken(string username, string password)
{
 string api = "";
 List<Token> list = new List<Token>();
 string url = "";
 Dictionary<string, string> dics = new Dictionary<string, string>
 {
   { "username", username },
   { "password", password },
   { "loginType", "account" },
   { "grantType", "password" }
 };
 string result = await Api.InvokeWebapi(url, api, "POST", dics);

 if (!string.IsNullOrEmpty(result))
 {
     JObject jsonObj = JObject.Parse(result);
     DataInfo info = new DataInfo();
     info.statusCode = Convert.ToInt32(jsonObj["code"]);
     info.message = jsonObj["message"].ToString();
     if (info.statusCode == 1)
     {
         JArray jlist = (JArray)jsonObj["data"];
         // 直接反序列化,简化代码
         foreach (var item in jlist)
         {
             Token ver = item.ToObject<Token>();
             list.Add(ver);
         }
     }
 }
 return list;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:40:18