Microsoft Graph 错误响应 - 如何从 JSON 中提取 HTTP 状态代码和内部错误代码?

2024-03-31

我目前正在我的 .NET Core 3.1 应用程序中测试 MS Graph .NET Core SDK 客户端。目的是提供我自己的本地 Web API 用户服务,该服务从 Azure B2C AD 执行更新/更改/获取用户。

在我的预期解决方案中,我将拥有各种 HTTP 客户端微服务,它们将向我的用户服务 SDK 客户端调用 API 命令,而不是直接使用 REST 调用 Azure Graph API。

在我的用户服务应用程序中,我尝试通过对发送到 Azure 的实际 SDK 命令使用存储库/接口方法来保持简洁。然后,这个相同的用户服务应用程序使用我自己的 WEB API 将数据返回到我的本地 HTTP 客户端。想象一下这个用户服务应用程序作为中间人的效果。

下图总结了环境:

这样做的目的是减少对图形服务使用的功能进行更改或添加时的工作,即在我自己的本地应用程序之间提供一些通信标准化,并促进更好的关注点分离。此外,如果 MS 对 Graph API 进行更改,那么我只会更新用户服务应用程序,而不是在所有 HTTP 客户端应用程序中进行代码更改。希望这是有道理的。

无论如何,现在进入正题!我的问题的原因:

(请耐心等待,我是 REST 和使用接口的新手)

Graph SDK 客户端和 Azure 中的 Graph Service API 之间遇到的任何错误都将记录在我的用户服务应用程序中,即我将在第一时间捕获的大量 json 错误详细信息,但是我根本不需要通过此级别的详细信息返回到我所有本地调用 HTTP 客户端。

我想要实现的是一种识别/捕获 SDK 客户端和图形服务之间遇到的任何 HTTP 状态代码错误的方法,以及错误的一些基本详细信息,即简短描述,并且仅传递这些较低级别的错误将详细信息返回给我的本地 HTTP 客户端,即保持干净。

我正在努力了解如何在我的代码中执行此操作,特别是考虑到我同时使用接口使其变得更加复杂。 MS 文档确实提供了有关使用图形服务的预期错误代码列表的信息,但没有示例解释如何处理此信息以便将相关(但较轻版本的信息)传递回另一个来源。

示例场景:

  1. 本地 HTTP 客户端调用 [HttpGet] GetUserById 到我的用户服务 Web API
  2. 然后,我的 Web API 使用 Graph SDK 客户端联系 Azure B2C、获取数据并返回。
  3. 然后,我的 WEB API 应检查收到的信息,如果找到用户,则将用户返回到我的调用 HTTP 客户端。
  4. 如果未找到用户,或者可能发出了错误的请求(缺少属性/错误的用户 ID 等),那么我需要检查收到的 HTTP 状态错误代码,并将相同的错误代码传递回我的调用 HTTP 客户端我只是想传回更简化的消息,例如未找到用户,而不是传回从 Graph Service 收到的大量 json 错误详细信息。
  5. 简化消息的逻辑方法是利用图形服务提供的已烘焙代码消息:

如下所示:“code”属性足以向任何调用 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 https://github.com/microsoftgraph/msgraph-sdk-dotnet-core/blob/9c89457f9215a691396f44fd85ef7e89e93f91d5/src/Microsoft.Graph.Core/Exceptions/ServiceException.cs。此类包括您正在寻找的属性:

/// <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);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Microsoft Graph 错误响应 - 如何从 JSON 中提取 HTTP 状态代码和内部错误代码? 的相关文章

随机推荐