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

别来无恙 提交于 2019-12-06 00:53:12

问题


I am trying to accomplish this task in which I need to send a list of id's (integers) to a web api 2 get request.

So I've found some samples here and it even has a sample project, but it doesn't work...

Here is my web api method code:

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

and here is the URL which I test in fiddler:

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

But the list is always empty and none of the id's are passing through to the method.

can't seem to understand if the problem is in the method, in the URL or in both...

So how this is possible to accomplish ?


回答1:


You'll need custom model binder to get this working. Here's simplified version you can start work with:

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;
    }
}

And use it this way (remove {ids} from route):

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

If you want to keep {ids} in route, you should change client request to:

api/NewHotelData/1,2,3,4

Another option (without custom model binder) is changing get request to:

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



回答2:


Using custom model binder as suggested in comments is the proper way to do this. However, you can also do it the quick-and-dirty way like so:

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

First, I'm splitting the uri ids string and then I'm converting them into a list of integers using Linq. Please beware that this is missing sanity checks and will throw expections if the arguments are in incorrect format.

You call it like this: http://192.168.9.43/api/NewHotelData?ids=5,10,20

Update: Personally, I think that using the model binder for a simple thing like this is over-engineering. You need a lot of code to make thing this simple work. The code you would use in a model binder is actually very similar, you would just get a nicer syntax of the method argument. If you wrap the integer parsing into a try-catch block and return an appropriate error message in case of bad format, I don't see a reason why not to use this approach.




回答3:


Apparently this could work out of the box:

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

That is, repeating the parameter name with the different values. But what would happen if those ids became huge and you had to include a lot of them, potentially making the URL too long?

I think it would be cleaner to just make it a POST request and be done with it, though. You wrote that you need the request to be a GET and not a POST, but why? Using POST to retrieve things is perfectly acceptable in the context of AJAX requests.




回答4:


This might be too tacky, but one could also do something like:
In your .NET class (model):

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

On the client side you'd do a post i.e: {myIntList: [4,2,0]}

Now the action/method on your controller would look something like:

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



回答5:


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

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



来源:https://stackoverflow.com/questions/38217534/how-to-send-a-list-of-integers-to-web-api-2-get-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!