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

.NET Core中如何通过Order Web API调用Catalog Web API?

在.NET Core中通过Order API调用Catalog API的实现方案

所需NuGet包

在Order.Api项目中安装以下包:

  • System.Net.Http.Json:简化HttpClient的JSON序列化/反序列化操作
  • (可选)Polly + Microsoft.Extensions.Http.Polly:实现请求重试、熔断等容错机制

实现步骤

1. 注册HttpClient到依赖注入容器

在Order.Api/Program.cs中添加HttpClient的注册,指定Catalog API的基础地址:

builder.Services.AddHttpClient<ICatalogService, CatalogService>(client =>
{
    // 替换为你的Catalog API实际运行地址
    client.BaseAddress = new Uri("http://localhost:5000/api/Catalog/");
    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
});

2. 创建Catalog API调用服务

封装调用逻辑到独立服务类,便于维护和测试:

服务接口(ICatalogService)

// Order.Api/Services/ICatalogService.cs
using CatalogAPI.Entities;

namespace Order.Api.Services;

public interface ICatalogService
{
    Task<Product?> GetProductByIdAsync(string productId);
    Task<IEnumerable<Product>> GetProductsAsync();
    Task<IEnumerable<Product>> GetProductsByCategoryAsync(string category);
}

服务实现(CatalogService)

// Order.Api/Services/CatalogService.cs
using System.Net.Http.Json;
using CatalogAPI.Entities;
using Microsoft.Extensions.Logging;

namespace Order.Api.Services;

public class CatalogService : ICatalogService
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<CatalogService> _logger;

    public CatalogService(HttpClient httpClient, ILogger<CatalogService> logger)
    {
        _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<Product?> GetProductByIdAsync(string productId)
    {
        try
        {
            return await _httpClient.GetFromJsonAsync<Product>($"{productId}");
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "调用Catalog API获取商品详情失败,商品ID:{ProductId}", productId);
            return null;
        }
    }

    public async Task<IEnumerable<Product>> GetProductsAsync()
    {
        try
        {
            return await _httpClient.GetFromJsonAsync<IEnumerable<Product>>("") ?? Enumerable.Empty<Product>();
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "调用Catalog API获取商品列表失败");
            return Enumerable.Empty<Product>();
        }
    }

    public async Task<IEnumerable<Product>> GetProductsByCategoryAsync(string category)
    {
        try
        {
            return await _httpClient.GetFromJsonAsync<IEnumerable<Product>>($"GetProductByCategory/{category}") ?? Enumerable.Empty<Product>();
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "调用Catalog API获取分类商品失败,分类:{Category}", category);
            return Enumerable.Empty<Product>();
        }
    }
}

3. 在OrderController中注入并调用服务

修改OrderController,注入ICatalogService并添加调用逻辑(示例:获取订单关联的商品详情):

// Order.Api/Controllers/OrderController.cs
using System.Net;
using Microsoft.AspNetCore.Mvc;
using OrderApi.Entities;
using OrderApi.Repositories;
using Order.Api.Services;
using CatalogAPI.Entities;

namespace OrderApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class OrderController : ControllerBase
{
    private readonly IOrderRepository _repository;
    private readonly ILogger<OrderController> _logger;
    private readonly ICatalogService _catalogService;

    public OrderController(IOrderRepository repository, ILogger<OrderController> logger, ICatalogService catalogService)
    {
        _repository = repository ?? throw new ArgumentNullException(nameof(repository));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _catalogService = catalogService ?? throw new ArgumentNullException(nameof(catalogService));
    }

    [HttpGet]
    [ProducesResponseType(typeof(IEnumerable<Order>), (int)HttpStatusCode.OK)]
    public async Task<ActionResult<IEnumerable<Order>>> GetOrders()
    {
        var orders = await _repository.GetOrders();
        return Ok(orders);
    }

    [HttpGet("{id}", Name = "GetOrder")]
    [ProducesResponseType((int)HttpStatusCode.NotFound)]
    [ProducesResponseType(typeof(Order), (int)HttpStatusCode.OK)]
    public async Task<ActionResult<Order>> GetOrderById(string id)
    {
        var order = await _repository.GetOrder(id);
        if (order == null)
        {
            _logger.LogError($"订单ID:{id} 不存在");
            return NotFound();
        }
        return Ok(order);
    }

    // 新增接口:获取指定订单关联的商品详情
    [HttpGet("{id}/products")]
    [ProducesResponseType((int)HttpStatusCode.NotFound)]
    [ProducesResponseType(typeof(IEnumerable<Product>), (int)HttpStatusCode.OK)]
    public async Task<ActionResult<IEnumerable<Product>>> GetOrderProducts(string id)
    {
        var order = await _repository.GetOrder(id);
        if (order == null)
        {
            _logger.LogError($"订单ID:{id} 不存在");
            return NotFound();
        }

        // 假设Order实体包含ProductIds属性,存储关联的商品ID集合
        var productIds = order.ProductIds;
        var products = new List<Product>();

        foreach (var productId in productIds)
        {
            var product = await _catalogService.GetProductByIdAsync(productId);
            if (product != null)
            {
                products.Add(product);
            }
        }

        return Ok(products);
    }
}

关键注意事项

  • 实体类共享:确保Product实体类能被Order.Api访问,可通过引用CatalogAPI项目或复制实体代码到Order.Api
  • 地址配置:将Catalog API的BaseAddress替换为实际运行地址,开发环境可参考launchSettings.json中的端口配置
  • 容错处理:若需要增强稳定性,可使用Polly库添加重试、超时、熔断等策略
  • 异常处理:在服务类中捕获HttpRequestException,记录日志并返回合理的默认值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:01:38