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

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

    You just need to add [FromUri] before parameter, looks like:

    GetCategories([FromUri] int[] categoryIds)
    

    And send request:

    /Categories?categoryids=1&categoryids=2&categoryids=3 
    
    0 讨论(0)
  • 2020-11-22 05:23

    If you want to list/ array of integers easiest way to do this is accept the comma(,) separated list of string and convert it to list of integers.Do not forgot to mention [FromUri] attriubte.your url look like:

    ...?ID=71&accountID=1,2,3,289,56

    public HttpResponseMessage test([FromUri]int ID, [FromUri]string accountID)
    {
        List<int> accountIdList = new List<int>();
        string[] arrAccountId = accountId.Split(new char[] { ',' });
        for (var i = 0; i < arrAccountId.Length; i++)
        {
            try
            {
               accountIdList.Add(Int32.Parse(arrAccountId[i]));
            }
            catch (Exception)
            {
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 05:26

    I recently came across this requirement myself, and I decided to implement an ActionFilter to handle this.

    public class ArrayInputAttribute : ActionFilterAttribute
    {
        private readonly string _parameterName;
    
        public ArrayInputAttribute(string parameterName)
        {
            _parameterName = parameterName;
            Separator = ',';
        }
    
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (actionContext.ActionArguments.ContainsKey(_parameterName))
            {
                string parameters = string.Empty;
                if (actionContext.ControllerContext.RouteData.Values.ContainsKey(_parameterName))
                    parameters = (string) actionContext.ControllerContext.RouteData.Values[_parameterName];
                else if (actionContext.ControllerContext.Request.RequestUri.ParseQueryString()[_parameterName] != null)
                    parameters = actionContext.ControllerContext.Request.RequestUri.ParseQueryString()[_parameterName];
    
                actionContext.ActionArguments[_parameterName] = parameters.Split(Separator).Select(int.Parse).ToArray();
            }
        }
    
        public char Separator { get; set; }
    }
    

    I am applying it like so (note that I used 'id', not 'ids', as that is how it is specified in my route):

    [ArrayInput("id", Separator = ';')]
    public IEnumerable<Measure> Get(int[] id)
    {
        return id.Select(i => GetData(i));
    }
    

    And the public url would be:

    /api/Data/1;2;3;4
    

    You may have to refactor this to meet your specific needs.

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

    I addressed this issue this way.

    I used a post message to the api to send the list of integers as data.

    Then I returned the data as an ienumerable.

    The sending code is as follows:

    public override IEnumerable<Contact> Fill(IEnumerable<int> ids)
    {
        IEnumerable<Contact> result = null;
        if (ids!=null&&ids.Count()>0)
        {
            try
            {
                using (var client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://localhost:49520/");
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    String _endPoint = "api/" + typeof(Contact).Name + "/ListArray";
    
                    HttpResponseMessage response = client.PostAsJsonAsync<IEnumerable<int>>(_endPoint, ids).Result;
                    response.EnsureSuccessStatusCode();
                    if (response.IsSuccessStatusCode)
                    {
                        result = JsonConvert.DeserializeObject<IEnumerable<Contact>>(response.Content.ReadAsStringAsync().Result);
                    }
    
                }
    
            }
            catch (Exception)
            {
    
            }
        }
        return result;
    }
    

    The receiving code is as follows:

    // POST api/<controller>
    [HttpPost]
    [ActionName("ListArray")]
    public IEnumerable<Contact> Post([FromBody]IEnumerable<int> ids)
    {
        IEnumerable<Contact> result = null;
        if (ids != null && ids.Count() > 0)
        {
            return contactRepository.Fill(ids);
        }
        return result;
    }
    

    It works just fine for one record or many records. The fill is an overloaded method using DapperExtensions:

    public override IEnumerable<Contact> Fill(IEnumerable<int> ids)
    {
        IEnumerable<Contact> result = null;
        if (ids != null && ids.Count() > 0)
        {
            using (IDbConnection dbConnection = ConnectionProvider.OpenConnection())
            {
                dbConnection.Open();
                var predicate = Predicates.Field<Contact>(f => f.id, Operator.Eq, ids);
                result = dbConnection.GetList<Contact>(predicate);
                dbConnection.Close();
            }
        }
        return result;
    }
    

    This allows you to fetch data from a composite table (the id list), and then return the records you are really interested in from the target table.

    You could do the same with a view, but this gives you a little more control and flexibility.

    In addition, the details of what you are seeking from the database are not shown in the query string. You also do not have to convert from a csv file.

    You have to keep in mind when using any tool like the web api 2.x interface is that the get, put, post, delete, head, etc., functions have a general use, but are not restricted to that use.

    So, while post is generally used in a create context in the web api interface, it is not restricted to that use. It is a regular html call that can be used for any purpose permitted by html practice.

    In addition, the details of what is going on are hidden from those "prying eyes" we hear so much about these days.

    The flexibility in naming conventions in the web api 2.x interface and use of regular web calling means you send a call to the web api that misleads snoopers into thinking you are really doing something else. You can use "POST" to really retrieve data, for example.

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

    Make the method type [HttpPost], create a model that has one int[] parameter, and post with json:

    /* Model */
    public class CategoryRequestModel 
    {
        public int[] Categories { get; set; }
    }
    
    /* WebApi */
    [HttpPost]
    public HttpResponseMessage GetCategories(CategoryRequestModel model)
    {
        HttpResponseMessage resp = null;
    
        try
        {
            var categories = //your code to get categories
    
            resp = Request.CreateResponse(HttpStatusCode.OK, categories);
    
        }
        catch(Exception ex)
        {
            resp = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
        }
    
        return resp;
    }
    
    /* jQuery */
    var ajaxSettings = {
        type: 'POST',
        url: '/Categories',
        data: JSON.serialize({Categories: [1,2,3,4]}),
        contentType: 'application/json',
        success: function(data, textStatus, jqXHR)
        {
            //get categories from data
        }
    };
    
    $.ajax(ajaxSettings);
    
    0 讨论(0)
提交回复
热议问题