如何将整数数组传递给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”来真正检索数据。
或者你可以传递一串分隔的项目,并将其放入接收端的数组或列表中。