我有一个ASP.NET Web API(第4版)REST服务,我需要传递一个整数数组。
这是我的操作方法:
public IEnumerable GetCategories(int[] categoryIds){
// code to retrieve categories from database
}
这是我尝试过的URL:
/Categories?categoryids=1,2,3,4
#1楼
您只需要在参数前添加[FromUri] ,如下所示:
GetCategories([FromUri] int[] categoryIds)
并发送请求:
/Categories?categoryids=1&categoryids=2&categoryids=3
#2楼
我最近亲自遇到了这一要求,因此决定实现一个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”,而不是“ ids”,因为这是我在路线中指定的方式):
[ArrayInput("id", Separator = ';')]
public IEnumerable Get(int[] id)
{
return id.Select(i => GetData(i));
}
公开网址为:
/api/Data/1;2;3;4
您可能需要重构它以满足您的特定需求。
#3楼
正如Filip W所指出的那样,您可能必须求助于这样的自定义模型绑定程序(已修改为绑定到实际的参数类型):
public IEnumerable 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阵列。
#4楼
public class ArrayInputAttribute : ActionFilterAttribute
{
private readonly string[] _ParameterNames;
///
///
///
public string Separator { get; set; }
///
/// cons
///
///
public ArrayInputAttribute(params string[] parameterName)
{
_ParameterNames = parameterName;
Separator = ",";
}
///
///
///
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
#5楼
万一有人需要-通过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不带参数名,不带括号。