C# ApiExplorer无法识别自定义类型的路由属性
我有一个项目,我想使用自定义类型的路由属性。 下面的代码将自定义类型作为查询参数,运行良好,帮助页面显示自定义类型C# ApiExplorer无法识别自定义类型的路由属性,c#,asp.net-web-api2,asp.net-web-api-helppages,C#,Asp.net Web Api2,Asp.net Web Api Helppages,我有一个项目,我想使用自定义类型的路由属性。 下面的代码将自定义类型作为查询参数,运行良好,帮助页面显示自定义类型 // GET api/values?5,6 [Route("api/values")] public string Get(IntegerListParameter ids) { return "value"; } WebApi.HelpPage提供了以下文档 如果我将代码更改为使用route属性,结果将得到一个空的帮助页面 // GET api/values/5,6
// GET api/values?5,6
[Route("api/values")]
public string Get(IntegerListParameter ids)
{
return "value";
}
WebApi.HelpPage提供了以下文档
如果我将代码更改为使用route属性,结果将得到一个空的帮助页面
// GET api/values/5,6
[Route("api/values/{ids}")]
public string Get(IntegerListParameter ids)
{
return "value";
}
当我检查HelpController.cs中的代码时,我发现ApiExplorer.apisdescriptions返回一个空的apisdescriptions集合
public ActionResult Index()
{
ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider();
Collection<ApiDescription> apiDescriptions = Configuration.Services.GetApiExplorer().ApiDescriptions;
return View(apiDescriptions);
}
public ActionResult Index()
{
ViewBag.DocumentationProvider=配置.Services.GetDocumentationProvider();
集合apiDescriptions=Configuration.Services.GetApiExplorer().apiDescriptions;
返回视图(API描述);
}
有没有办法让ApiExplorer将我的自定义类IntegerListParameter识别为属性路由?不确切地确定
IntegerListParameter
列表是什么数据结构,但是如果需要在查询中发送逗号分隔的整数列表(例如~api/products?ids=1,2,3,4
),可以使用筛选器属性。可在此处找到此示例实现:您需要:
IntegerListParameter
类型添加HttpParameterBindingIValueProviderParameterBinding
并实现ValueProviderFactorys
IntegerListParameter
添加一个转换器,并为typeof(string)
参数覆盖CanConvertFrom
方法ObjectId
,请参见我的示例:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//...
config.ParameterBindingRules.Insert(0, GetCustomParameterBinding);
TypeDescriptor.AddAttributes(typeof(ObjectId), new TypeConverterAttribute(typeof(ObjectIdConverter)));
//...
}
public static HttpParameterBinding GetCustomParameterBinding(HttpParameterDescriptor descriptor)
{
if (descriptor.ParameterType == typeof(ObjectId))
{
return new ObjectIdParameterBinding(descriptor);
}
// any other types, let the default parameter binding handle
return null;
}
}
public class ObjectIdParameterBinding : HttpParameterBinding, IValueProviderParameterBinding
{
public ObjectIdParameterBinding(HttpParameterDescriptor desc)
: base(desc)
{
}
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
{
try
{
SetValue(actionContext, new ObjectId(actionContext.ControllerContext.RouteData.Values[Descriptor.ParameterName] as string));
return Task.CompletedTask;
}
catch (FormatException)
{
throw new BadRequestException("Invalid id format");
}
}
public IEnumerable<ValueProviderFactory> ValueProviderFactories { get; } = new[] { new QueryStringValueProviderFactory() };
}
public class ObjectIdConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
}
公共静态类WebApiConfig
{
公共静态无效寄存器(HttpConfiguration配置)
{
//...
config.ParameterBindingRules.Insert(0,GetCustomParameterBinding);
AddAttributes(typeof(ObjectId),新的TypeConverterAttribute(typeof(objectdConverter));
//...
}
公共静态HttpParameterBinding GetCustomParameterBinding(HttpParameterDescriptor描述符)
{
if(descriptor.ParameterType==typeof(ObjectId))
{
返回新的ObjectdParameterBinding(描述符);
}
//任何其他类型,让默认参数绑定处理
返回null;
}
}
公共类ObjectdParameterBinding:HttpParameterBinding、IValueProviderParameterBinding
{
公共对象参数绑定(HttpParameterDescriptor描述)
:基础(描述)
{
}
公共覆盖任务ExecuteBindingAsync(ModelMetadataProvider metadataProvider、HttpActionContext actionContext、CancellationToken CancellationToken)
{
尝试
{
SetValue(actionContext,新ObjectId(actionContext.ControllerContext.RouteData.Values[Descriptor.ParameterName]作为字符串));
返回Task.CompletedTask;
}
捕获(格式化异常)
{
抛出新的BadRequestException(“无效的id格式”);
}
}
public IEnumerable ValueProviderFactorys{get;}=new[]{new QueryStringValueProviderFactory()};
}
公共类ObjectdConverter:TypeConverter
{
公共覆盖布尔CanConvertFrom(ITypeScriptorContext上下文,类型sourceType)
{
if(sourceType==typeof(string))
返回true;
返回base.CanConvertFrom(上下文,sourceType);
}
}
我已经实现了逗号分隔的整数列表。作为查询参数和属性路由,它都可以很好地工作。我的问题是帮助页面没有显示列表是属性路由的操作。问题在于,当列表作为属性路由实现时,ApiExplorer.apisdescriptions无法识别该操作。这在试图找出自定义模型绑定器(逗号分隔的整数数组)为什么没有显示在Api Explorer或Swagger中时很有帮助,感谢您将其组合在一起!