ApiExplorer does not recognize route attributes with custom type

前端 未结 2 1331
离开以前
离开以前 2021-01-24 18:37

I have a project where I want to use route attributes with a custom type. The following code where I have the custom type as a query parameter works fine and the help page displ

2条回答
  •  孤城傲影
    2021-01-24 19:22

    You need to:

    1. add HttpParameterBinding for your IntegerListParameter type
    2. mark the binding as IValueProviderParameterBinding and implement ValueProviderFactories
    3. add a converter for IntegerListParameter and override CanConvertFrom method for typeof(string) parameter

    After these actions, route with custom type IntegerListParameter must be recognized in ApiExplorer.

    See my example for type 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 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);
        }
    }
    

提交回复
热议问题