1

So i want to slice a "IQueryable" in C# ASP.NET Web Api but i can't make it work. With the code below it might get more clear what i want to do.

private TestTwoContext db = new TestTwoContext();


// GET: api/Fruits/thefruits
[HttpGet]
[Route("api/Fruits/thefruits")]
public IQueryable<Fruits> TheFruits()
{
    dynamic myList = db.Fruits;
    var FiveItems = Queryable.Take(Queryable.Skip(myList, 5), 5);
    return FiveItems;
}

this gives me error in browser console:

jquery-3.3.1.min.js:2 GET http://localhost:49771/api/Fruits/thefruits 500 (Internal Server Error)

i need to cut my list (db.Fruits) from the 5th element to the 10th element. Just like we slice arrays in JavaScript. Example:

var myList = array.slice(5, 10)

I have also tried this:

private TestTwoContext db = new TestTwoContext();


// GET: api/Fruits/thefruits
[HttpGet]
[Route("api/Fruits/thefruits")]
public IQueryable<Fruits> TheFruits()
{
    var myList = db.Fruits;
    var FiveItems = myList.Skip(5).Take(4);
    return FiveItems;
}

this gives me error in browser console: jquery-3.3.1.min.js:2 GET http://localhost:49771/api/Fruits/thefruits 500 (Internal Server Error)

the number in skip and take will be passed as parametars but that is not that part i am worried about... those number are just example for now. Any help would be appreciated.

This Conroler works without problems:

// GET: api/Fruits
public IQueryable<Fruits> GetFruits()
{
    return db.Fruits;
}

returns the whole list of fruits, which later i write it down in table in HTML.

This also works :

[HttpGet]
[Route("api/Fruits/thefruits")]
public IQueryable<Fruits> TheFruits()
{
    var myList = db.Fruits;
    var FiveItems = myList.Take(5);
    return FiveItems;
}

but it gives me the the first 5 elements... not from the 5th to 10th element.

johnny 5
  • 19,893
  • 50
  • 121
  • 195
Happy Coconut
  • 973
  • 4
  • 14
  • 33
  • Please include the actual and expected results from your attempts. ["It's not working" is not helpful](http://idownvotedbecau.se/itsnotworking/) – Igor Jun 20 '18 at 17:31
  • What isn't working exactly? `.Skip(x).Take(y)` is a pretty common technique. Other than your variable assumes you're getting 5 items but you're only taking 4. – DavidG Jun 20 '18 at 17:31
  • Oh, and also you can't return an `IQueryable` over a WebAPI. You really should return `IEnumerable` and `return FiveItems.ToList();` – DavidG Jun 20 '18 at 17:33
  • If this will be based on arguments that are passed in, does the selection have to be based on index? Or could you pass in the specific properties of Fruit you're selecting for? – jdmac020 Jun 20 '18 at 17:39
  • `Skip` and `Take` are extension methods and are intended to be used as if they were class methods: `db.Fruits.Skip(5).Take(5)`. Also, why is `myList` dynamic? That doesn't offer anything useful, in fact it hurts performance and type safety. – NetMage Jun 20 '18 at 17:40
  • Status `500` / `Internal Server Error` = You have an unhandled exception at run time in your server code. Use your c# IDE debugger (probably visual studio) and see what it is and then include that exception and its details in the question. The other option is to add error handling and logging to get the exception and its details. – Igor Jun 20 '18 at 17:52

4 Answers4

4

It would be nice if you posted the 500 error but as a guess, it's probably because cannot Skip without calling an order by in EntityFramework

[HttpGet]
[Route("api/Fruits/thefruits")]
public IQueryable<Fruits> TheFruits()
{
    return db.Fruits.OrderBy(x => x.Id).Skip(4).Take(5);
}
johnny 5
  • 19,893
  • 50
  • 121
  • 195
  • No problem, Anytime! – johnny 5 Jun 20 '18 at 18:30
  • Maybe a stupid question but what if don't want to order them by id. can this work without the order by id? – Happy Coconut Jun 20 '18 at 18:33
  • 1
    You need an order by clause if you really don't care for the order just do `.OrderBy(x => 1)` which will return the same value for all – johnny 5 Jun 20 '18 at 18:34
  • 1
    @HappyCoconut @johnny5 You may not care about the ordering but it’s not guaranteed that the database always reads the table in the same way. If it chooses to read the table differently (for whatever reason) and you don’t provide a proper order, your Skip/Take will return the non-continuous subsets/pages. Therefore, don’t use `OrderBy(x => 1)` if you don’t want to risk that your paging returns random pages. – ckuri Jun 20 '18 at 21:55
  • @ckuri yes Thats what I meant by if you don’t care about the order, but I probably should of clarified that a bit more because of the side effects – johnny 5 Jun 20 '18 at 22:04
0

Try this to understand Skip() and Take().

var list = new List<long>{0,1,2,3,4,5,6,7,8,9};
var secondList = list.AsQueryable().Skip(5).Take(5).ToList();
secondList

Skip(X) -> It ignores the first X items on the Iqueryable

Take(Y) -> Limits the max resultant results.

OUTPUT IS:

List<long>(5) { 5, 6, 7, 8, 9 }
-1

Try updating your "TheFruits" method to the following:

// GET: api/Fruits/thefruits
[HttpGet]
[Route("api/Fruits/thefruits")]
public IQueryable<Fruits> TheFruits()
{
    dynamic myList = db.Fruits;
    var FiveItems = myList.Skip(5).Take(5);
    return FiveItems;
}

Sample Console app:

    using System.Linq;

    static void Main(string[] args)
    {
        int[] test = new[] { 1, 2, 3, 4, 5, 6, 7, 8 };

        var t = test.AsQueryable().Skip(5).Take(5);

        foreach (int i in t)
        {
            Console.WriteLine(i.ToString());
        }

        Console.ReadLine();
    }
Kevin
  • 151
  • 3
  • 11
  • nope... still same error: jquery-3.3.1.min.js:2 GET http://localhost:49771/api/Fruits/thefruits 500 (Internal Server Error) – Happy Coconut Jun 20 '18 at 18:00
  • Can you provide some error details? I've edited my answer to show a sample console app which shows that this should work for you. – Kevin Jun 20 '18 at 18:00
  • The error message that you've pasted seems to indicate an issue with the client-side JavaScript rather than the Controller's Action. I'd recommend debugging the Action's return value. – Kevin Jun 20 '18 at 18:08
  • 1
    @Kevin What makes you think that a *server error* is an indication of a problem with the client? The *server* is what has an error. You can run the code yourself to see what the actual exception is that resulted in a 500 error being sent to the client. – Servy Jun 20 '18 at 18:15
-1

This is what i had to do to make it work:

    [HttpGet]
    [Route("api/Fruits/thefruits")]
     public List<Fruits> TheFruits()
    {

        var myList = db.Fruits;
        var FiveItems = myList.AsEnumerable().Skip(5).Take(5).ToList();
        return FiveItems;

    }
Happy Coconut
  • 973
  • 4
  • 14
  • 33