如何将整数列表发送到 web api 2 get 请求?

How to send a list of integers to web api 2 get request?

我正在尝试完成此任务,其中我需要将 ID(整数)列表发送到 Web api 2 get 请求。

所以我找到了一些示例 here 它甚至有一个示例项目,但它不起作用...

这是我的网站api方法代码:

[HttpGet]
[Route("api/NewHotelData/{ids}")]
public HttpResponseMessage Get([FromUri] List<int> ids)
{
    // ids.Count is 0
    // ids is empty...
}

这是我在 fiddler 中测试的 URL:

http://192.168.9.43/api/NewHotelData/?ids=1,2,3,4

但列表始终为空,并且 none 个 ID 正在传递给该方法。

似乎无法理解问题出在方法、URL 还是两者...

那么这是如何实现的呢?

按照评论中的建议使用自定义模型活页夹是执行此操作的正确方法。但是,您也可以像这样快速而简单地进行操作:

[HttpGet]
[Route("api/NewHotelData")]
public HttpResponseMessage Get([FromUri] string ids)
{
    var separated = ids.Split(new char[] { ',' });
    List<int> parsed = separated.Select(s => int.Parse(s)).ToList();
}

首先,我拆分 uri ids 字符串,然后使用 Linq 将它们转换为整数列表。请注意,这缺少健全性检查,如果参数格式不正确,将会引发预期。

你这样称呼它:http://192.168.9.43/api/NewHotelData?ids=5,10,20

更新:就我个人而言,我认为将模型绑定器用于像这样简单的事情是过度工程化。您需要大量代码才能使事情变得如此简单。您将在模型绑定器中使用的代码实际上是 very similar,您只会获得更好的方法参数语法。如果您将整数解析包装到一个 try-catch 块中,并且 return 在格式错误的情况下显示适当的错误消息,我看不出为什么不使用这种方法。

[HttpGet]
[Route("api/getsomething")]
public HttpResponseMessage Get([FromUri] params int[] ids)
{
}

用法:http GET localhost:9000/api/getsomething?ids=1&ids=5&ids=9

显然这可以开箱即用:

http://192.168.9.43/api/NewHotelData/?ids=1&ids=2&ids=3&ids=4

也就是用不同的值重复参数名。但是,如果这些 ID 变得很大并且您必须包含很多 ID,可能会使 URL 太长,会发生什么情况?

不过,我认为将其设为 POST 请求并完成它会更简洁。您写道,您 需要 请求是 GET 而不是 POST,但为什么呢?在 AJAX 请求的上下文中,使用 POST 检索内容是完全可以接受的。

您需要自定义模型活页夹才能使其正常工作。这是您可以开始工作的简化版本:

public class CsvIntModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var key = bindingContext.ModelName;
        var valueProviderResult = bindingContext.ValueProvider.GetValue(key);
        if (valueProviderResult == null)
        {
            return false;
        }

        var attemptedValue = valueProviderResult.AttemptedValue;
        if (attemptedValue != null)
        {
            var list = attemptedValue.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).
                       Select(v => int.Parse(v.Trim())).ToList();

            bindingContext.Model = list;
        }
        else
        {
            bindingContext.Model = new List<int>();
        }
        return true;
    }
}

并以这种方式使用它(从路由中删除 {ids}):

[HttpGet]
[Route("api/NewHotelData")]
public HttpResponseMessage Get([ModelBinder(typeof(CsvIntModelBinder))] List<int> ids)

如果你想在路由中保留 {ids},你应该将客户端请求更改为:

api/NewHotelData/1,2,3,4

另一个选项(没有自定义模型活页夹)正在将获取请求更改为:

?ids=1&ids=2&ids=3

这可能太俗气了,但也可以这样做:
在您的 .NET class(模型)中:

public class TackyList
{
     public IEnumerable<int> myIntList {get; set;}
}

在客户端你会做一个post即:{myIntList: [4,2,0]}

现在您控制器上的 action/method 看起来像:

public void myApiMethodThatDoesSomethingWith(TackyList tl)
{
   // here you should be able to do something like:
   if(tl != null && tl.Count > 0) // blah
}