如何将整数数组传递给ASP.NET Web API?

我有asp.net web apirest服务,我需要传递一个整数数组。 这怎么能在asp.net 4 web api中完成。

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

url访问上述服务

 /Categories?categoryids=1,2,3,4 

您只需在参数前添加[FromUri] ,如下所示:

 GetCategories([FromUri] int[] categoryIds) 

并发送请求:

 /Categories?categoryids=1&categoryids=2&categoryids=3 

正如Filip W指出的那样,你可能不得不求助于一个像这样的自定义模型绑定器(修改为绑定到实际的paramtypes):

 public IEnumerable<Category> GetCategories([ModelBinder(typeof(CommaDelimitedArrayModelBinder))]long[] categoryIds) { // do your thing } public class CommaDelimitedArrayModelBinder : IModelBinder { public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { var key = bindingContext.ModelName; var val = bindingContext.ValueProvider.GetValue(key); if (val != null) { var s = val.AttemptedValue; if (s != null) { var elementType = bindingContext.ModelType.GetElementType(); var converter = TypeDescriptor.GetConverter(elementType); var values = Array.ConvertAll(s.Split(new[] { ","},StringSplitOptions.RemoveEmptyEntries), x => { return converter.ConvertFromString(x != null ? x.Trim() : x); }); var typedValues = Array.CreateInstance(elementType, values.Length); values.CopyTo(typedValues, 0); bindingContext.Model = typedValues; } else { // change this line to null if you prefer nulls to empty arrays bindingContext.Model = Array.CreateInstance(bindingContext.ModelType.GetElementType(), 0); } return true; } return false; } } 

然后你可以说:

/Categories?categoryids=1,2,3,4和ASP.NET Web API将正确绑定您的categoryIds数组。

我最近自己碰到了这个需求,于是我决定实现一个ActionFilter来处理这个问题。

 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; } } 

我像这样应用它(请注意,我使用'id',而不是'id',因为它是如何在我的路线中指定的):

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

公共url是:

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

你可能不得不重构这个来满足你的特定需求。

如果有人需要 – 通过POST而不是FromUri实现相同或类似的事情(如删除),请使用FromBody和客户端(JS / jQuery)格式参数为$.param({ '': categoryids }, true)

C#:

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

jQuery的:

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

$.param({ '': categoryids }, true)是这样的:.net将期望post body包含urlencoded值,如=1&=2&=3不带参数名称,不带括号。

您可以尝试使用此代码,以逗号分隔值/值的数组从WebAPI获取JSON

  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; } } 

输出:

 [ {"CategoryID":"4","CategoryName":"Category_4"}, {"CategoryID":"5","CategoryName":"Category_5"}, {"CategoryID":"3","CategoryName":"Category_3"} ] 

简单的方法发送数组params到web api

API

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

jquery:发送JSON对象作为请求参数

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

它将生成您的请求url,如../api/categories/GetCategories?categoryIds=1&categoryIds=2&categoryIds=3&categoryIds=4

 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)); } } 

用法:

  [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); } 

请求uri

 http://localhost/api/v1/files/2a9937c7-8201-59b7-bc8d-11a9178895d0/tags/BBA5CD5D-F07D-47A9-8DEE-D19F5FA65F63,BBA5CD5D-F07D-47A9-8DEE-D19F5FA65F63 

如果你想列表/整数数组最简单的方法是接受逗号(,)分隔列表中的string,并将其转换为整数列表。不要忘记提及[FromUri] attriubte.your url的样子:

…?ID = 71&帐户ID = 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) { } } } 

使方法types为[HttpPost],创build一个具有一个int []参数的模型,并使用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); 

我用这种方式解决了这个问题。

我用一个post消息给api发送整数列表作为数据。

然后,我把这些数据作为一个永恒的数据返回。

发送代码如下:

 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; } 

接收代码如下:

 // 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; } 

它对一条logging或许多logging来说工作得很好。 填充是使用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; } 

这使您可以从组合表(ID列表)中获取数据,然后从目标表中返回您真正感兴趣的logging。

你可以用一个视图来做同样的事情,但是这会给你更多的控制权和灵活性。

另外,查询string中不显示您要从数据库中查找的详细信息。 您也不必从csv文件转换。

你必须记住,当使用任何工具,如web api 2.x接口的get,put,post,delete,head等等函数都有一个通用的用法,但不限于这个用法。

所以,虽然后期通常在web api界面的创build上下文中使用,但并不仅限于此。 这是一个普通的 html调用,可以用于任何由html实践允许的目的。

另外,关于这些事情的细节,从我们这些日子听到的那些“窥探的眼睛”中隐藏起来。

Web api 2.x界面中的命名规则的灵活性以及常规Web调用的使用意味着你发送一个调用web api来误导snoopers,以为你真的在做别的事情。 例如,您可以使用“POST”来真正检索数据。

或者你可以传递一串分隔的项目,并将其放入接收端的数组或列表中。