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

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

    Easy way to send array params to web api

    API

    public IEnumerable<Category> GetCategories([FromUri]int[] categoryIds){
     // code to retrieve categories from database
    }
    

    Jquery : send JSON object as request params

    $.get('api/categories/GetCategories',{categoryIds:[1,2,3,4]}).done(function(response){
    console.log(response);
    //success response
    });
    

    It will generate your request URL like ../api/categories/GetCategories?categoryIds=1&categoryIds=2&categoryIds=3&categoryIds=4

    0 讨论(0)
  • 2020-11-22 05:05
    public class ArrayInputAttribute : ActionFilterAttribute
    {
        private readonly string[] _ParameterNames;
        /// <summary>
        /// 
        /// </summary>
        public string Separator { get; set; }
        /// <summary>
        /// cons
        /// </summary>
        /// <param name="parameterName"></param>
        public ArrayInputAttribute(params string[] parameterName)
        {
            _ParameterNames = parameterName;
            Separator = ",";
        }
    
        /// <summary>
        /// 
        /// </summary>
        public void ProcessArrayInput(HttpActionContext actionContext, string parameterName)
        {
            if (actionContext.ActionArguments.ContainsKey(parameterName))
            {
                var parameterDescriptor = actionContext.ActionDescriptor.GetParameters().FirstOrDefault(p => p.ParameterName == parameterName);
                if (parameterDescriptor != null && parameterDescriptor.ParameterType.IsArray)
                {
                    var type = parameterDescriptor.ParameterType.GetElementType();
                    var parameters = String.Empty;
                    if (actionContext.ControllerContext.RouteData.Values.ContainsKey(parameterName))
                    {
                        parameters = (string)actionContext.ControllerContext.RouteData.Values[parameterName];
                    }
                    else
                    {
                        var queryString = actionContext.ControllerContext.Request.RequestUri.ParseQueryString();
                        if (queryString[parameterName] != null)
                        {
                            parameters = queryString[parameterName];
                        }
                    }
    
                    var values = parameters.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries)
                        .Select(TypeDescriptor.GetConverter(type).ConvertFromString).ToArray();
                    var typedValues = Array.CreateInstance(type, values.Length);
                    values.CopyTo(typedValues, 0);
                    actionContext.ActionArguments[parameterName] = typedValues;
                }
            }
        }
    
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            _ParameterNames.ForEach(parameterName => ProcessArrayInput(actionContext, parameterName));
        }
    }
    

    Usage:

        [HttpDelete]
        [ArrayInput("tagIDs")]
        [Route("api/v1/files/{fileID}/tags/{tagIDs}")]
        public HttpResponseMessage RemoveFileTags(Guid fileID, Guid[] tagIDs)
        {
            _FileRepository.RemoveFileTags(fileID, tagIDs);
            return Request.CreateResponse(HttpStatusCode.OK);
        }
    

    Request uri

    http://localhost/api/v1/files/2a9937c7-8201-59b7-bc8d-11a9178895d0/tags/BBA5CD5D-F07D-47A9-8DEE-D19F5FA65F63,BBA5CD5D-F07D-47A9-8DEE-D19F5FA65F63
    
    0 讨论(0)
  • 2020-11-22 05:06

    In case someone would need - to achieve same or similar thing(like delete) via POST instead of FromUri, use FromBody and on client side(JS/jQuery) format param as $.param({ '': categoryids }, true)

    c#:

    public IHttpActionResult Remove([FromBody] int[] categoryIds)
    

    jQuery:

    $.ajax({
            type: 'POST',
            data: $.param({ '': categoryids }, true),
            url: url,
    //...
    });
    

    The thing with $.param({ '': categoryids }, true) is that it .net will expect post body to contain urlencoded value like =1&=2&=3 without parameter name, and without brackets.

    0 讨论(0)
  • 2020-11-22 05:06

    You may try this code for you to take comma separated values / an array of values to get back a JSON from webAPI

     public class CategoryController : ApiController
     {
         public List<Category> Get(String categoryIDs)
         {
             List<Category> categoryRepo = new List<Category>();
    
             String[] idRepo = categoryIDs.Split(',');
    
             foreach (var id in idRepo)
             {
                 categoryRepo.Add(new Category()
                 {
                     CategoryID = id,
                     CategoryName = String.Format("Category_{0}", id)
                 });
             }
             return categoryRepo;
         }
     }
    
     public class Category
     {
         public String CategoryID { get; set; }
         public String CategoryName { get; set; }
     } 
    

    Output :

    [
    {"CategoryID":"4","CategoryName":"Category_4"}, 
    {"CategoryID":"5","CategoryName":"Category_5"}, 
    {"CategoryID":"3","CategoryName":"Category_3"} 
    ]
    
    0 讨论(0)
  • 2020-11-22 05:06

    Or you could just pass a string of delimited items and put it into an array or list on the receiving end.

    0 讨论(0)
  • 2020-11-22 05:06

    My solution was to create an attribute to validate strings, it does a bunch of extra common features, including regex validation that you can use to check for numbers only and then later I convert to integers as needed...

    This is how you use:

    public class MustBeListAndContainAttribute : ValidationAttribute
    {
        private Regex regex = null;
        public bool RemoveDuplicates { get; }
        public string Separator { get; }
        public int MinimumItems { get; }
        public int MaximumItems { get; }
    
        public MustBeListAndContainAttribute(string regexEachItem,
            int minimumItems = 1,
            int maximumItems = 0,
            string separator = ",",
            bool removeDuplicates = false) : base()
        {
            this.MinimumItems = minimumItems;
            this.MaximumItems = maximumItems;
            this.Separator = separator;
            this.RemoveDuplicates = removeDuplicates;
    
            if (!string.IsNullOrEmpty(regexEachItem))
                regex = new Regex(regexEachItem, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var listOfdValues = (value as List<string>)?[0];
    
            if (string.IsNullOrWhiteSpace(listOfdValues))
            {
                if (MinimumItems > 0)
                    return new ValidationResult(this.ErrorMessage);
                else
                    return null;
            };
    
            var list = new List<string>();
    
            list.AddRange(listOfdValues.Split(new[] { Separator }, System.StringSplitOptions.RemoveEmptyEntries));
    
            if (RemoveDuplicates) list = list.Distinct().ToList();
    
            var prop = validationContext.ObjectType.GetProperty(validationContext.MemberName);
            prop.SetValue(validationContext.ObjectInstance, list);
            value = list;
    
            if (regex != null)
                if (list.Any(c => string.IsNullOrWhiteSpace(c) || !regex.IsMatch(c)))
                    return new ValidationResult(this.ErrorMessage);
    
            return null;
        }
    }
    
    0 讨论(0)
提交回复
热议问题