【问题标题】:How to send a list of integers to web api 2 get request?如何将整数列表发送到 web api 2 获取请求?
【发布时间】:2016-11-08 02:57:11
【问题描述】:

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

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

这是我的 web 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

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

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

那么这怎么可能实现呢?

【问题讨论】:

标签: c# asp.net-web-api2 get-request


【解决方案1】:

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

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

【讨论】:

  • 这是正确的,但不要从路由中删除{ids}。没有它就不行。
  • 如果你按照要求使用它就可以工作?ids=1,2,3,4
【解决方案2】:

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

[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 块中并在格式错误的情况下返回适当的错误消息,我看不出为什么不使用这种方法。

【讨论】:

  • 谢谢,但我对这种方式很熟悉。如果你能提供一个如何使用模型绑定器来解决这个问题的示例,那就太好了:-)
  • 你说得对,我可能同意你的看法,但这是我的要求,我需要按照告知的去做:-)
  • 当然,这是你的决定:)
【解决方案3】:
[HttpGet]
[Route("api/getsomething")]
public HttpResponseMessage Get([FromUri] params int[] ids)
{
}

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

【讨论】:

  • 这可行,但我的要求是在没有方法名称的情况下调用该方法,如下所示:localhost:9000/api/?ids=1&ids=5&ids=9,但这不起作用。 ..
【解决方案4】:

显然这可以开箱即用:

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

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

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

【讨论】:

  • @LiranFriedman 好的,但是重复参数名称有效吗?这才是最重要的,其他的都是我自己的想法。
  • 我不确定,因为到目前为止还没有值到达服务器。
【解决方案5】:

这可能太俗气了,但也可以这样做:
在您的 .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
}

【讨论】:

    猜你喜欢
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    相关资源
    最近更新 更多