c# - Microsoft Graph 错误响应 - 如何从 JSON 中提取 HTTP 状态代码和内部错误代码?
问题描述
我目前正在我的 .NET Core 3.1 应用程序中测试 MS Graph .NET Core SDK 客户端。目的是提供我自己的本地 Web API 用户服务,该服务从 Azure B2C AD 执行更新/更改/获取用户。
在我的预期解决方案中,我将拥有各种 HTTP 客户端微服务,它们将调用 API 命令到我的用户服务 SDK 客户端,而不是直接使用 REST 调用 Azure Graph API。
在我的用户服务应用程序中,我试图通过对发送到 Azure 的实际 SDK 命令使用存储库/接口方法来保持清洁。然后,同一用户服务应用程序使用我自己的 WEB API 将数据返回给我的本地 HTTP 客户端。将这个用户服务应用想象成中间人效应。
下图总结环境:
这样做的目的是减少对 Graph Service 使用的功能进行更改或添加时的工作,即在我自己的本地应用程序之间提供一些通信标准化,并促进更好的关注点分离。此外,如果 MS 对 Graph API 进行了更改,那么我只是在更新用户服务应用程序,而不是在我的所有 HTTP 客户端应用程序中进行代码更改。希望这是有道理的。
无论如何,现在进入重点!我的问题的原因:
(请耐心等待,我是 REST 和使用接口的新手)
Graph SDK 客户端和 Azure 中的 Graph 服务 API 之间遇到的任何错误都将记录在我的用户服务应用程序中,即我将在第一时间捕获的大量 json 错误详细信息,但是我根本不需要通过这个级别详细信息返回给我所有的本地调用 HTTP 客户端。
我想要实现的是一种识别/捕获在 SDK 客户端和图形服务之间遇到的任何 HTTP 状态代码错误的方法,以及错误的一些基本细节,即简短描述并且只通过这些较低级别将详细信息返回给我的本地 HTTP 客户端,即保持清洁。
我正在努力了解如何在我的代码中执行此操作,特别是考虑到我同时使用接口的事实使它变得更加复杂。MS 文档确实提供了有关使用图形服务的预期错误代码列表的信息,但是没有示例说明如何处理此信息以便将相关(但更轻的信息版本)传回给另一个来源。
示例场景:
- 本地 HTTP 客户端向我的用户服务 Web API 调用 [HttpGet] GetUserById
- 然后,我的 Web API 使用 Graph SDK 客户端与 Azure B2C 联系,获取数据并返回。
- 然后,我的 WEB API 应该检查收到的信息,如果发现用户很好,则将用户返回给我的调用 HTTP 客户端。
- 如果找不到用户,或者可能发出了错误的请求(缺少属性/错误的用户 ID 等),那么我需要检查收到的 HTTP 状态错误代码并将相同的错误代码传递回我的调用 HTTP 客户端,同时时间,而不是传回从 Graph Service 收到的大量 json 错误详细信息,我只想传回更简化的消息,例如找不到用户。
- 简化消息的逻辑方法是利用 Graph Service 提供的已经烘焙的代码消息:
如下所示:“代码”属性足以向任何调用 HTTP 客户端解释情况,如果我需要进一步调查,那么我会检查日志:
{
"error": {
"code": "invalidRange",
"message": "Uploaded fragment overlaps with existing data.",
"innerError": {
"requestId": "request-id",
"date": "date-time"
}
}
}
我只是无法弄清楚如何提取从通过 SDK 对图形服务的调用接收到的 HTTP 状态代码,以及如何从正文中的 json 错误消息中获取单个属性,然后返回这个简化/简化的以正确和符合的方式将信息返回给我自己的 HTTP 客户端。到目前为止,我自己的项目代码如下:
我的用户服务 WEB API 控制器:
[HttpGet("{id}")]
public async Task<IActionResult> GetUserById(string id)
{
try
{
var user = await _repository.GetUserByIdAsync(id);
}
catch(Exception ex)
{
// What am I catching here? how do I get the HTTP Status Code that
was received from the call to the Graph Service in the event of an error?
// How do i extract the code error key/value from the json received from Graph Service?
}
// Finally, how do I return this captured info to the HTTP Client?
// Ignore this part, not sufficient for my needs.
//if (user == null) return BadRequest();
//if (user != null) return Ok(user);
//else return NotFound();
}
我的界面:
namespace MicrosoftGraph_API.Repository
{
public interface IGraphClientRepo
{
public Task<List<User>> GetAllUsersAsync();
public Task<User> GetUserByIdAsync(string id);
}
}
我的 Graph SDK 客户端类:
public class GraphSDKClientRepo : IGraphClientRepo
{
public readonly IUserServiceClient _IUserServiceClient;
public GraphSDKClientRepo(IUserServiceClient userServiceClient)
{
_IUserServiceClient = userServiceClient;
}
public async Task<User> GetUserByIdAsync(string id)
{
var graphClient = _IUserServiceClient.InitializeGraphClient();
// Get user by object ID
var result = await graphClient.Users[id]
.Request()
.Select(e => new
{
e.DisplayName,
e.Id,
e.Identities
})
.GetAsync();
return result;
}
}
解决方案
如果您的调用遇到错误,SDK 将抛出一个ServiceException
. 此类包括您要查找的属性:
/// <summary>
/// The HTTP status code from the response.
/// </summary>
public System.Net.HttpStatusCode StatusCode { get; }
因此,您对 Graph 的调用将类似于:
public async Task<User> GetUserByIdAsync(string id)
{
var graphClient = _IUserServiceClient.InitializeGraphClient();
// Get user by object ID
try
{
return await graphClient
.Users[id]
.Request()
.Select("id,displayName,identities")
.GetAsync();
}
catch (ServiceException)
{
throw;
}
}
你的控制器代码看起来像
[HttpGet("{id}")]
public async Task<IActionResult> GetUserById(string id)
{
try
{
return this.Ok(await _repository.GetUserByIdAsync(id));
}
catch (ServiceException ex)
{
return this.StatusCode(se.StatusCode);
}
}
如果您需要通过 HTTP 状态以不同方式处理异常,您也可以这样做
[HttpGet("{id}")]
public async Task<IActionResult> GetUserById(string id)
{
try
{
return this.Ok(await _repository.GetUserByIdAsync(id));
}
catch (ServiceException e) when(e.StatusCode == System.Net.HttpStatusCode.NotFound)
{
//
// Do "Not Found" stuff
//
return this.StatusCode(e.StatusCode);
}
catch (ServiceException e) when(e.StatusCode == System.Net.HttpStatusCode.BadRequest)
{
//
// Do "Bad Request" stuff
//
return this.StatusCode(e.StatusCode);
}
catch (ServiceException e)
{
return this.StatusCode(e.StatusCode);
}
}
推荐阅读
- python - 横河示波器的 Pyvisa 解码问题
- javascript - Azure JavaScript 函数输出到服务总线队列
- python-3.x - pyAlsaaudio 在 openSUSE 上安装
- .net - discord.net 如何转换为 IEmote
- c++ - Qt moveToThread 仅在第一次工作
- excel-formula - 如何在 Excel 中的多个单元格中广播一个值?
- android - DATE_CHANGED 的广播接收器仅适用于 TIMEZONE_CHANGED
- bash - 如何使用文件中的行作为 grep 的关键字?
- r - 使用 purrr 在相同大小的向量列表中拆分向量
- python-3.x - 尝试将virtualenv与vs代码一起使用,当解释器是python3时,文件是python 2而不是3