2

我有一个项目,我想在其中使用自定义类型的路由属性。我将自定义类型作为查询参数的以下代码工作正常,帮助页面显示自定义类型。

// GET api/values?5,6
[Route("api/values")]
public string Get(IntegerListParameter ids)
{
    return "value";
}

WebApi.HelpPage 提供以下文档 Help:Page

如果我更改代码以使用路由属性,结果是我得到一个空的帮助页面。

// GET api/values/5,6
[Route("api/values/{ids}")]
public string Get(IntegerListParameter ids)
{
    return "value";
}

当我检查我在 HelpController.cs 中观察到的代码时,ApiExplorer.ApiDescriptions 返回一个空的 ApiDescriptions 集合

public ActionResult Index()
{
    ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider();
    Collection<ApiDescription> apiDescriptions = Configuration.Services.GetApiExplorer().ApiDescriptions;

    return View(apiDescriptions);
}

有什么方法可以让 ApiExplorer 将我的自定义类 IntegerListParameter 识别为属性路由?

4

2 回答 2

2

你需要:

  1. IntegerListParameter为您的类型添加 HttpParameterBinding
  2. 将绑定标记为IValueProviderParameterBinding并实施ValueProviderFactories
  3. 为参数添加转换器IntegerListParameter和覆盖CanConvertFrom方法typeof(string)

在这些操作之后,必须在 ApiExplorer 中识别具有自定义类型 IntegerListParameter 的路由。

请参阅我的类型示例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);
    }
}
于 2017-11-05T16:35:18.957 回答
0

不完全确定数据结构IntegerListParameter列表是什么,但如果您需要在查询中发送以逗号分隔的整数列表(例如~api/products?ids=1,2,3,4),您可以使用过滤器属性。可以在此处找到一个示例实现:Convert custom action filter for Web API use?

于 2016-12-16T07:46:19.210 回答