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

前端 未结 17 2028
孤独总比滥情好
孤独总比滥情好 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:11

    ASP.NET Core 2.0 Solution (Swagger Ready)

    Input

    DELETE /api/items/1,2
    DELETE /api/items/1
    

    Code

    Write the provider (how MVC knows what binder to use)

    public class CustomBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
    
            if (context.Metadata.ModelType == typeof(int[]) || context.Metadata.ModelType == typeof(List))
            {
                return new BinderTypeModelBinder(typeof(CommaDelimitedArrayParameterBinder));
            }
    
            return null;
        }
    }
    

    Write the actual binder (access all sorts of info about the request, action, models, types, whatever)

    public class CommaDelimitedArrayParameterBinder : IModelBinder
    {
    
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
    
            var value = bindingContext.ActionContext.RouteData.Values[bindingContext.FieldName] as string;
    
            // Check if the argument value is null or empty
            if (string.IsNullOrEmpty(value))
            {
                return Task.CompletedTask;
            }
    
            var ints = value?.Split(',').Select(int.Parse).ToArray();
    
            bindingContext.Result = ModelBindingResult.Success(ints);
    
            if(bindingContext.ModelType == typeof(List))
            {
                bindingContext.Result = ModelBindingResult.Success(ints.ToList());
            }
    
            return Task.CompletedTask;
        }
    }
    

    Register it with MVC

    services.AddMvc(options =>
    {
        // add custom binder to beginning of collection
        options.ModelBinderProviders.Insert(0, new CustomBinderProvider());
    });
    

    Sample usage with a well documented controller for Swagger

    /// 
    /// Deletes a list of items.
    /// 
    /// The list of unique identifiers for the  items.
    /// The deleted item.
    /// The item was successfully deleted.
    /// The item is invalid.
    [HttpDelete("{itemIds}", Name = ItemControllerRoute.DeleteItems)]
    [ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)]
    [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)]
    public async Task Delete(List itemIds)
    => await _itemAppService.RemoveRangeAsync(itemIds);
    

    EDIT: Microsoft recommends using a TypeConverter for these kids of operations over this approach. So follow the below posters advice and document your custom type with a SchemaFilter.

提交回复
热议问题