我有一个ASP。NET Web API(版本4)REST服务,我需要传递一个整数数组。
下面是我的动作方法:
public IEnumerable<Category> GetCategories(int[] categoryIds){
// code to retrieve categories from database
}
这是我试过的网址:
/Categories?categoryids=1,2,3,4
我有一个ASP。NET Web API(版本4)REST服务,我需要传递一个整数数组。
下面是我的动作方法:
public IEnumerable<Category> GetCategories(int[] categoryIds){
// code to retrieve categories from database
}
这是我试过的网址:
/Categories?categoryids=1,2,3,4
当前回答
我的解决方案是创建一个属性来验证字符串,它做了一堆额外的公共功能,包括regex验证,你可以使用它来检查数字,然后我根据需要转换为整数…
你可以这样使用:
public class MustBeListAndContainAttribute : ValidationAttribute
{
private Regex regex = null;
public bool RemoveDuplicates { get; }
public string Separator { get; }
public int MinimumItems { get; }
public int MaximumItems { get; }
public MustBeListAndContainAttribute(string regexEachItem,
int minimumItems = 1,
int maximumItems = 0,
string separator = ",",
bool removeDuplicates = false) : base()
{
this.MinimumItems = minimumItems;
this.MaximumItems = maximumItems;
this.Separator = separator;
this.RemoveDuplicates = removeDuplicates;
if (!string.IsNullOrEmpty(regexEachItem))
regex = new Regex(regexEachItem, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var listOfdValues = (value as List<string>)?[0];
if (string.IsNullOrWhiteSpace(listOfdValues))
{
if (MinimumItems > 0)
return new ValidationResult(this.ErrorMessage);
else
return null;
};
var list = new List<string>();
list.AddRange(listOfdValues.Split(new[] { Separator }, System.StringSplitOptions.RemoveEmptyEntries));
if (RemoveDuplicates) list = list.Distinct().ToList();
var prop = validationContext.ObjectType.GetProperty(validationContext.MemberName);
prop.SetValue(validationContext.ObjectInstance, list);
value = list;
if (regex != null)
if (list.Any(c => string.IsNullOrWhiteSpace(c) || !regex.IsMatch(c)))
return new ValidationResult(this.ErrorMessage);
return null;
}
}
其他回答
将方法类型设置为[HttpPost],创建一个有一个int[]参数的模型,并使用json post:
/* 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);
如果你想列出/数组的整数,最简单的方法是接受逗号(,)分隔的字符串列表,并将其转换为整数列表。不要忘记提到[FromUri]属性。你的url看起来像:
... ?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)
{
}
}
}
我已经创建了一个自定义模型绑定器,它将任何逗号分隔的值(仅为原语、十进制、浮点数、字符串)转换为相应的数组。
public class CommaSeparatedToArrayBinder<T> : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
Type type = typeof(T);
if (type.IsPrimitive || type == typeof(Decimal) || type == typeof(String) || type == typeof(float))
{
ValueProviderResult val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (val == null) return false;
string key = val.RawValue as string;
if (key == null) { bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Wrong value type"); return false; }
string[] values = key.Split(',');
IEnumerable<T> result = this.ConvertToDesiredList(values).ToArray();
bindingContext.Model = result;
return true;
}
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Only primitive, decimal, string and float data types are allowed...");
return false;
}
private IEnumerable<T> ConvertToDesiredArray(string[] values)
{
foreach (string value in values)
{
var val = (T)Convert.ChangeType(value, typeof(T));
yield return val;
}
}
}
以及如何在Controller中使用:
public IHttpActionResult Get([ModelBinder(BinderType = typeof(CommaSeparatedToArrayBinder<int>))] int[] ids)
{
return Ok(ids);
}
我最近遇到了这个需求,我决定实现一个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<Measure> Get(int[] id)
{
return id.Select(i => GetData(i));
}
public url是:
/api/Data/1;2;3;4
您可能必须对其进行重构以满足您的特定需求。
或者,您可以只传递一串分隔项,并将其放入接收端的数组或列表中。