Hi all,
I was wondering how people were going about sorting a table in asp.net mvc? I've heard of javascript solutions that work pretty well with non-paged tables, such as jquery's table sorter, but i need a solution that will work with paged tables.
The project i'm working on currently uses the following solution, but i find it very messy.
Controller
public ActionResult Sort(string parameter)
{
IEnumerable<IProduct> list;
if (Session["Model"] != null)
list = (IEnumerable<IProduct>)Session["Model"]).ToList<IProduct>();
else
list = _service.GetAll();
if (Session["parameter"] == null && Session["sortDirection"] == null)
{
//set the parameter and set the sort to desc
Session["parameter"] = parameter;
Session["sortDirection"] = "DESC";
}
else if (Session["parameter"] != null) //already set so not the first time
{
//same parameter sent
if (Session["parameter"].ToString().Equals(parameter))
{
//check sort direction and reverse
if (Session["sortDirection"].ToString().Equals("DESC"))
Session["sortDirection"] = "ASC";
else
Session["sortDirection"] = "DESC";
}
else //different parameter sent
{
Session["sortDirection"] = "DESC";
Session["parameter"] = parameter;
}
}
if (Session["sortDirection"].CompareTo("ASC") == 0)
list = Models.ContollerHelpers.SortingHelper.OrderBy(list.AsQueryable(), column);
else
list = Models.ContollerHelpers.SortingHelper.OrderByDescending(list.AsQueryable(), column);
return View("Results", list.ToList);
}
Helper
public class Helper()
{
private static IOrderedQueryable<T> OrderingHelper<T>(IQueryable<T> source, string propertyName, bool descending, bool anotherLevel)
{
ParameterExpression param = Expression.Parameter(typeof(T), string.Empty); // I don't care about some naming
MemberExpression property = Expression.PropertyOrField(param, propertyName);
LambdaExpression sort = Expression.Lambda(property, param);
MethodCallExpression call = Expression.Call(
typeof(Queryable),
(!anotherLevel ? "OrderBy" : "ThenBy") + (descending ? "Descending" : string.Empty),
new[] { typeof(T), property.Type },
source.Expression,
Expression.Quote(sort));
return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(call);
}
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
{
return OrderingHelper(source, propertyName, false, false);
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string propertyName)
{
return OrderingHelper(source, propertyName, true, false);
}
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string propertyName)
{
return OrderingHelper(source, propertyName, false, true);
}
public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string propertyName)
{
return OrderingHelper(source, propertyName, true, true);
}
}
List View
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Models.Interface.IProduct>>" %>
<% Session["model"] = Model; %>
<table>
<tr>
<th>
Edit Details
</th>
<th>
<%=Html.ActionLink("Id","Sort",new {parameter ="Id"}) %>
</th>
<th>
<%=Html.ActionLink("Name", "Sort", new { parameter = "Name"})%>
</th>
<th>
<%=Html.ActionLink("Status", "Sort", new { parameter = "Status" })%>
</th>
<th>
<%=Html.ActionLink("Notes", "Sort", new { parameter = "Notes"})%>
</th>
</tr>
<% foreach (var item in Model){ %>
<tr>
<td>
<%= Html.ActionLink("Edit", "Edit", new { id=item.Id }) %> |
</td>
<td>
<%= Html.Encode(item.Id) %>
</td>
<td>
<%= Html.Encode(item.Name) %>
</td>
<td>
<%= Html.Encode(item.Status) %>
</td>
<td>
<%= Html.Encode(item.Notes) %>
</td>
</tr>
<% } %>
</table>
Is this the only way of doing something like this? If anyone knows of a nicer way that doesn't involve having all of the records being loaded to a page at once then please link to examples.
Thanks