.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
相关产品推荐
相关产品推荐

