如何在Swashbuckle、Swagger和NSwag中使用自定义模型绑定器?
ASP.NET Core Web API 处理CSV格式ID列表的端点实现
刚好我之前做过类似的实现,分享一下我的ASP.NET Core Web API端点,用来接收CSV格式的ID列表,返回对应Model对象的JSON数组:
端点核心代码
这个端点通过GET请求接收URL路径里的CSV参数,使用自定义模型绑定器解析成字符串集合,再返回对应的模型数据:
[HttpGet] [Route("models/{ids}")] [Produces(typeof(IEnumerable<Model>))] public IActionResult Get([ModelBinder(typeof(CsvModelBinder<string>))] IEnumerable<string> ids) { // 这里替换成你的业务逻辑,比如从数据库/缓存中获取对应ID的模型 var models = _modelDataSource.GetModelsByIds(ids); return Ok(models); }
端点特性说明
[HttpGet]:标记该端点响应GET请求[Route("models/{ids}")]:定义路由模板,{ids}是路径参数,支持类似/models/a,b,c的CSV格式输入[Produces(typeof(IEnumerable<Model>))]:声明端点的响应类型为Model对象的集合,帮助Swagger等工具生成正确的文档[ModelBinder(typeof(CsvModelBinder<string>))]:指定使用自定义的CSV模型绑定器来解析ids参数,将CSV字符串转换为IEnumerable<string>
自定义CsvModelBinder实现
因为ASP.NET Core默认的模型绑定器无法直接将CSV格式的字符串转换为集合类型,所以我实现了IModelBinder接口来处理这个转换逻辑:
public class CsvModelBinder<T> : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) throw new ArgumentNullException(nameof(bindingContext)); // 获取路由中的ids参数值 var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueProviderResult == ValueProviderResult.None) return Task.CompletedTask; bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); var csvValue = valueProviderResult.FirstValue; if (string.IsNullOrWhiteSpace(csvValue)) return Task.CompletedTask; // 分割CSV字符串并转换为目标类型 var values = csvValue.Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(item => (T)Convert.ChangeType(item.Trim(), typeof(T))); // 设置绑定结果 bindingContext.Result = ModelBindingResult.Success(values); return Task.CompletedTask; } }
这个通用的绑定器支持任意可转换的类型(比如int、Guid),只要调整泛型参数即可,比如CsvModelBinder<int>就能把CSV字符串转换成整数集合。
使用示例
当客户端发送请求:
GET /models/1001,1002,1003
绑定器会把路径中的"1001,1002,1003"解析为包含"1001"、"1002"、"1003"的IEnumerable<string>,控制器就可以用这个集合去查询对应的模型数据,最终返回类似下面的JSON响应:
[ {"id": "1001", "name": "Model A"}, {"id": "1002", "name": "Model B"}, {"id": "1003", "name": "Model C"} ]
内容的提问来源于stack exchange,提问作者Ray Saltrelli
相关产品推荐
相关产品推荐

