The method 'OrderBy' must be called before the method 'Skip' Exception

asp.net-mvc-3, entity-framework, linq-to-entities, mvcjqgrid

Solution

The exception means that you always need a sorted input if you apply `Skip`, also in the case that the user doesn't click on a column to sort by. I could imagine that no sort column is specified when you open the grid view for the first time before the user can even click on a column header. To catch this case I would suggest to define some default sorting that you want when no other sorting criterion is given, for example:

switch (sortColumn)
{
    case "JobDescriptionID":
        return (sortOrder == "desc")
            ? jobdescriptions.OrderByDescending(j => j.JobDescriptionID)
            : jobdescriptions.OrderBy(j => j.JobDescriptionID);

    case "JobDescriptionTitle":
        return (sortOrder == "desc")
            ? jobdescriptions.OrderByDescending(j => j.JobDescriptionTitle)
            : jobdescriptions.OrderBy(j => j.JobDescriptionTitle);

    // etc.

    default:
        return jobdescriptions.OrderBy(j => j.JobDescriptionID);
}

Edit

About your follow-up problems according to your comment: You cannot use `ToString()` in a LINQ to Entities query. And the next problem would be that you cannot create a `string` array in a query. I would suggest to load the data from the DB with their native types and then convert afterwards to strings (and to the string array) in memory:

rows = (from j in jobdescription
        select new
        {
            JobDescriptionID = j.JobDescriptionID,
            JobTitle = j.JobTitle,
            JobTypeName = j.JobType.JobTypeName,
            JobPriorityName = j.JobPriority.JobPriorityName,
            Rate = j.JobType.Rate,
            CreationDate = j.CreationDate,
            JobDeadline = j.JobDeadline
        })
        .AsEnumerable() // DB query runs here, the rest is in memory
        .Select(a => new
        {
            id = a.JobDescriptionID,
            cell = new[] 
            { 
                a.JobDescriptionID.ToString(), 
                a.JobTitle,
                a.JobTypeName,
                a.JobPriorityName,
                a.Rate.ToString(),
                a.CreationDate.ToShortDateString(),
                a.JobDeadline.ToShortDateString()
            }
        })
        .ToArray()

Problem

I was trying to implement the `jQgrid` using `MvcjQgrid` and i got this exception. ``` System.NotSupportedException was unhandled by user code Message=The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'. ``` Though OrdeyBy is used before Skip method why it is generating the exception? How can it be solved? I encountered the exception in the controller: ``` public ActionResult GridDataBasic(GridSettings gridSettings) { var jobdescription = sm.GetJobDescription(gridSettings); var totalJobDescription = sm.CountJobDescription(gridSettings); var jsonData = new { total = totalJobDescription / gridSettings.PageSize + 1, page = gridSettings.PageIndex, records = totalJobDescription, rows = ( from j in jobdescription select new { id = j.JobDescriptionID, cell = new[] { j.JobDescriptionID.ToString(), j.JobTitle, j.JobType.JobTypeName, j.JobPriority.JobPriorityName, j.JobType.Rate.ToString(), j.CreationDate.ToShortDateString(), j.JobDeadline.ToShortDateString(), } }).ToArray() }; return Json(jsonData, JsonRequestBehavior.AllowGet); } ``` GetJobDescription Method and CountJobDescription Method ``` public int CountJobDescription(GridSettings gridSettings) { var jobdescription = _dataContext.JobDescriptions.AsQueryable(); if (gridSettings.IsSearch) { jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription); } return jobdescription.Count(); } public IQueryable<JobDescription> GetJobDescription(GridSettings gridSettings) { var jobdescription = orderJobDescription(_dataContext.JobDescriptions.AsQueryable(), gridSettings.SortColumn, gridSettings.SortOrder); if (gridSettings.IsSearch) { jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription); } return jobdescription.Skip((gridSettings.PageIndex - 1) * gridSettings.PageSize).Take(gridSettings.PageSize); } ``` And Finally FilterJobDescription and OrderJobDescription ``` private static IQueryable<JobDescription> FilterJobDescription(IQueryable<JobDescription> jobdescriptions, Rule rule) { if (rule.field == "JobDescriptionID") { int result; if (!int.TryParse(rule.data, out result)) return jobdescriptions; return jobdescriptions.Where(j => j.JobDescriptionID == Convert.ToInt32(rule.data)); } // Similar Statements return jobdescriptions; } private IQueryable<JobDescription> orderJobDescription(IQueryable<JobDescription> jobdescriptions, string sortColumn, string sortOrder) { if (sortColumn == "JobDescriptionID") return (sortOrder == "desc") ? jobdescriptions.OrderByDescending(j => j.JobDescriptionID) : jobdescriptions.OrderBy(j => j.JobDescriptionID); return jobdescriptions; } ```

Original source