9

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

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

这是我的 web api 方法代码:

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

这是我在提琴手中测试的网址:

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

但是该列表始终为空,并且没有任何 id 传递给该方法。

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

那么这怎么可能实现呢?

4

5 回答 5

12

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

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
于 2016-07-06T07:25:08.180 回答
9

按照评论中的建议使用自定义模型绑定器是执行此操作的正确方法。但是,您也可以像这样快速而肮脏的方式来做到这一点:

[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();
}

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

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

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

于 2016-07-06T06:55:40.780 回答
1
[HttpGet]
[Route("api/getsomething")]
public HttpResponseMessage Get([FromUri] params int[] ids)
{
}

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

于 2016-07-06T06:58:28.180 回答
1

显然这可以开箱即用:

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

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

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

于 2016-07-06T07:03:36.143 回答
1

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

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

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

现在你的控制器上的动作/方法看起来像:

public void myApiMethodThatDoesSomethingWith(TackyList tl)
{
   // here you should be able to do something like:
   if(tl != null && tl.Count > 0) // blah
}
于 2017-04-24T23:59:34.500 回答