.NET 5 WebAPI + OData:如何通过自定义模型优化响应格式并统一异常处理
当然可以实现!我来一步步给你拆解怎么做,完全贴合你的需求:
实现步骤
1. 创建统一的泛型响应模型
首先我们定义一个泛型类,用来封装所有场景的响应(正常、无结果、异常),这样就能保证格式统一:
public class ApiResponse<T> { // 对应你要的responseMessage public string ResponseMessage { get; set; } // 自定义响应码 public int ResponseCode { get; set; } // 替代@odata.count的itemsLength public int ItemsLength { get; set; } // 存放数据的items数组,默认初始化空列表 public List<T> Items { get; set; } = new List<T>(); }
(注:ASP.NET Core默认的JSON序列化会自动把PascalCase的属性名转成camelCase,刚好匹配你想要的响应格式)
2. 处理OData查询,生成自定义响应
接下来在你的OData接口里,我们手动处理OData查询参数,避免返回默认的OData响应字段(比如@odata.context)。这里用ODataQueryOptions来解析前端的OData查询(比如$filter、$orderBy这些):
[HttpGet] public IActionResult Get(ODataQueryOptions<Customer> options) { // 获取原始查询集 var baseQuery = _context.Customers.AsQueryable(); // 应用OData查询规则 var filteredQuery = options.ApplyTo(baseQuery) as IQueryable<Customer>; // 获取总条数和数据列表 var totalCount = filteredQuery?.Count() ?? 0; var dataItems = filteredQuery?.ToList() ?? new List<Customer>(); // 处理无结果的场景,设置自定义消息 string responseMsg; int responseCode = 10; // 你的成功响应码 if (totalCount == 0) { responseMsg = "没有找到匹配的客户数据"; } else { responseMsg = "成功获取客户数据"; } // 组装自定义响应 var apiResponse = new ApiResponse<Customer> { ResponseMessage = responseMsg, ResponseCode = responseCode, ItemsLength = totalCount, Items = dataItems }; // 返回自定义响应,不会包含任何OData默认字段 return Ok(apiResponse); }
3. 全局异常处理,统一异常响应格式
为了让异常场景也使用同一个响应模型,我们可以创建一个全局异常过滤器,自动捕获所有未处理的异常并返回指定格式:
public class GlobalExceptionFilter : IExceptionFilter { public void OnException(ExceptionContext context) { // 组装异常响应 var errorResponse = new ApiResponse<object> { ResponseMessage = $"{context.Exception.Message} - Exception message example text.", ResponseCode = -1, ItemsLength = 0, Items = new List<object>() }; // 设置响应状态码为500(可根据需求调整) context.Result = new ObjectResult(errorResponse) { StatusCode = StatusCodes.Status500InternalServerError }; // 标记异常已处理,避免框架默认处理 context.ExceptionHandled = true; } }
然后在Startup.cs里注册这个过滤器:
public void ConfigureServices(IServiceCollection services) { services.AddControllers(options => { // 添加全局异常过滤器 options.Filters.Add<GlobalExceptionFilter>(); }) .AddOData(options => { // 启用需要的OData查询功能(比如过滤、排序、计数等) options.Select().Filter().OrderBy().Count().Expand().SetMaxTop(100); // 注册OData路由和EDM模型 options.AddRouteComponents("api", GetEdmModel()); }); // 其他服务配置... }
效果验证
- 正常有数据时:返回你想要的格式,没有
@odata.context - 查询无结果时:
responseMessage会显示自定义的无结果提示 - 接口抛出异常时:自动返回
responseCode=-1的异常格式,items为空数组
这样就完全实现了你所有的需求!
内容的提问来源于stack exchange,提问作者TronComputers
相关产品推荐
相关产品推荐

