Pass an array of integers to ASP.NET Web API?

前端 未结 17 2001
孤独总比滥情好
孤独总比滥情好 2020-11-22 04:40

I have an ASP.NET Web API (version 4) REST service where I need to pass an array of integers.

Here is my action method:



        
17条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-11-22 05:15

    I originally used the solution that @Mrchief for years (it works great). But when when I added Swagger to my project for API documentation my end point was NOT showing up.

    It took me a while, but this is what I came up with. It works with Swagger, and your API method signatures look cleaner:

    In the end you can do:

        // GET: /api/values/1,2,3,4 
    
        [Route("api/values/{ids}")]
        public IHttpActionResult GetIds(int[] ids)
        {
            return Ok(ids);
        }
    

    WebApiConfig.cs

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Allow WebApi to Use a Custom Parameter Binding
            config.ParameterBindingRules.Add(descriptor => descriptor.ParameterType == typeof(int[]) && descriptor.ActionDescriptor.SupportedHttpMethods.Contains(HttpMethod.Get)
                                                               ? new CommaDelimitedArrayParameterBinder(descriptor)
                                                               : null);
    
            // Allow ApiExplorer to understand this type (Swagger uses ApiExplorer under the hood)
            TypeDescriptor.AddAttributes(typeof(int[]), new TypeConverterAttribute(typeof(StringToIntArrayConverter)));
    
            // Any existing Code ..
    
        }
    }
    

    Create a new class: CommaDelimitedArrayParameterBinder.cs

    public class CommaDelimitedArrayParameterBinder : HttpParameterBinding, IValueProviderParameterBinding
    {
        public CommaDelimitedArrayParameterBinder(HttpParameterDescriptor desc)
            : base(desc)
        {
        }
    
        /// 
        /// Handles Binding (Converts a comma delimited string into an array of integers)
        /// 
        public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider,
                                                 HttpActionContext actionContext,
                                                 CancellationToken cancellationToken)
        {
            var queryString = actionContext.ControllerContext.RouteData.Values[Descriptor.ParameterName] as string;
    
            var ints = queryString?.Split(',').Select(int.Parse).ToArray();
    
            SetValue(actionContext, ints);
    
            return Task.CompletedTask;
        }
    
        public IEnumerable ValueProviderFactories { get; } = new[] { new QueryStringValueProviderFactory() };
    }
    

    Create a new class: StringToIntArrayConverter.cs

    public class StringToIntArrayConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
        }
    }
    

    Notes:

    • https://stackoverflow.com/a/47123965/862011 pointed me in the right direction
    • Swagger was only failing to pick my comma delimited end points when using the [Route] attribute

提交回复
热议问题