我有一個ASP.NET Web API(第4版)REST服務,我須要傳遞一個整數數組。 ajax
這是個人操做方法: 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)
併發送請求: ide
/Categories?categoryids=1&categoryids=2&categoryids=3
我最近親自遇到了這一要求,所以決定實現一個ActionFilter
來處理此要求。 ui
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」,而不是「 ids」,由於這是我在路線中指定的方式): this
[ArrayInput("id", Separator = ';')] public IEnumerable<Measure> Get(int[] id) { return id.Select(i => GetData(i)); }
公開網址爲: url
/api/Data/1;2;3;4
您可能須要重構它以知足您的特定需求。 spa
正如Filip W所指出的那樣,您可能必須求助於這樣的自定義模型綁定程序(已修改成綁定到實際的參數類型): .net
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
陣列。
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
萬一有人須要-經過POST
而不是FromUri
來實現相同或類似的事情(例如刪除),請使用FromBody
並在客戶端(JS / jQuery) FromBody
param設置爲$.param({ '': categoryids }, true)
C#:
public IHttpActionResult Remove([FromBody] int[] categoryIds)
jQuery的:
$.ajax({ type: 'POST', data: $.param({ '': categoryids }, true), url: url, //... });
帶有$.param({ '': categoryids }, true)
是.net指望後正文包含urlencoded值,例如=1&=2&=3
不帶參數名,不帶括號。