C#调用MS Graph API搜索SharePoint文件报500错误(Graph Explorer正常)
问题现象
- 调用Microsoft Graph的
/search/query接口搜索SharePoint文件时,在Microsoft Graph Explorer中可正常返回正确结果 - 替换为C#代码实现后,接口返回
Status Code: 500Reason Phrase: Internal Server Error - 接口返回的错误详情如下:
{ "error": { "code": "System.NullReferenceException", "message": "Object reference not set to an instance of an object.", "innerError": { "date": "2021-03-19T16:16:28", "request-id": "f3092cda-b813-4507-928e-7e2de84fc88f", "client-request-id": "f3092cda-b813-4507-928e-7e2de84fc88f" } } } - 涉及的C#实现代码片段:
var searchTerm = "164377_07323_03122021_112659_TaxApp"; var headerStr = @"{{""requests"": [{{""entityTypes"": [""listItem""],""query"": {{""queryString"": ""{0}""}}}}]}}"; headerStr = string.Format(headerStr, searchTerm); var headerJson = JsonConvert.SerializeObject(headerStr); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResponse.AccessToken); var content = new StringContent(headerJson, Encoding.UTF8, "application/json"); HttpResponseMessage response = httpClient.PostAsync("https://graph.microsoft.com/v1.0/search/query", content).Result; var postResult = response.Content.ReadAsStringAsync().Result;
代码核心错误点
- 对已经构造完成的JSON字符串做了二次序列化,导致最终发送的请求体格式完全不符合接口要求
原代码中headerStr经过string.Format处理后,已经是符合接口要求的结构化JSON文本,但后续执行JsonConvert.SerializeObject(headerStr)时,会把整段字符串作为一个普通文本值序列化,最终生成的内容是被双引号包裹、内部所有双引号都带转义字符的无效JSON字符串,不是服务端可解析的JSON对象 - 服务端拿到无法解析的请求体后,尝试读取不存在的请求结构字段,最终触发空引用异常,返回500错误
修复方案
- 修正请求体构造逻辑,取消多余的二次序列化
优先使用强类型对象构造请求结构,再做单次序列化,避免手动拼接JSON时出现转义错误,示例代码:var searchTerm = "164377_07323_03122021_112659_TaxApp"; // 按接口要求定义匿名对象结构,完全匹配Graph Search接口的入参格式 var searchRequestPayload = new { requests = new[] { new { entityTypes = new[] { "listItem" }, query = new { queryString = searchTerm } } } }; // 仅做一次序列化生成合法JSON请求体 var requestBody = JsonConvert.SerializeObject(searchRequestPayload); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResponse.AccessToken); var content = new StringContent(requestBody, Encoding.UTF8, "application/json"); // 替换.Result阻塞调用为async/await模式,避免线程死锁风险 HttpResponseMessage response = await httpClient.PostAsync("https://graph.microsoft.com/v1.0/search/query", content); var postResult = await response.Content.ReadAsStringAsync(); - 对齐请求细节:和Graph Explorer中实际发送的请求做逐项对比,确认
Content-Type、Authorization头、权限范围完全一致,排除因请求格式不匹配导致的服务端解析异常
通用排查步骤
- 打印C#代码实际发送的完整请求体,和Graph Explorer抓包的真实请求体逐字符对比,定位格式差异
- 使用同一访问令牌、同一请求体,通过本地接口调试工具复现调用,区分是代码构造请求的问题,还是网络、权限配置的问题
- 借助接口返回的
request-id,在对应租户的Graph调用日志中查询详细的服务端堆栈信息,定位具体解析失败点
内容的提问来源于stack exchange,提问作者Ashok
相关产品推荐
相关产品推荐

