Wednesday, September 16, 2009 11:06 PM
Kazi Manzur Rashid
Telerik ASP.NET MVC Grid Preview (Take 1)
Those who have seen my tweet, already know that we have started working on our ASP.NET MVC Grid. In post I will show you the very early version of our Grid, so that you can provide your valuable feedback to guide us in the right direction. So far, we have implemented the paging and multi-column sorting. Let me show you the minimum code to set it up.
First, we will create an action method which creates some random data for view:
public ActionResult Basic()
{
Random rnd = new Random();
IList<InMemoryCustomer> model = new List<InMemoryCustomer>();
for (int i = 1; i <= 100; i++)
{
InMemoryCustomer c = new InMemoryCustomer
{
Id = rnd.Next(1, 1000),
Name = string.Format("Dummy Name #{0}", i),
Address = string.Format("Dummy Address #{0}", i),
RegisterAt = DateTime.Now.AddMonths(-rnd.Next(1, 48)).AddDays(-rnd.Next(0, 365)),
Balance = rnd.Next(1000, 10000),
IsActive = ((i % 4) == 0)
};
model.Add(c);
}
return View(model);
}
Next, in the view:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<InMemoryCustomer>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
In Memory
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Basic</h2>
<% Html.Telerik().Grid<InMemoryCustomer>()
.Name("MyGrid")
.Columns(
columns =>
{
columns.Add(c => c.Id);
columns.Add(c => c.Name);
columns.Add(c => c.Address);
columns.Add(c => c.RegisterAt).Format("{0:MM/dd/yyyy}");
columns.Add(c => c.IsActive).HeaderText("Active");
}
)
.SortMode(GridSortMode.MultiColumn)
.Pager(pager => pager.PageSize(10).Style(GridPagerStyle.FirstPreviousNextLast))
.BindTo(Model)
.Render(); %>
</asp:Content>
When you run the above, it will show you a nice looking grid like the following:
Check that when defining the columns, we are using strongly typed syntax which means you will get the complete benefit of compile time checking, also note that we have set the SortMode to MultiColumn, other values are SingleColumn and None. When you click any of the column headers or the links in the pager, it will append the order by and page number in the query string like the following:
?MyGrid-orderBy=Name asc%2CAddress desc&MyGrid-page=2 // Order By Name Ascending, Address Descending and Page is 2
?MyGrid-orderBy=Name asc%2CRegisterAt asc //Order By Name Ascending, RegisterAt Ascending and Page is 1 that why it is not added
As you can see, we are also using the Grid Name as prefix for the query string parameters, this is required to identify the parameter when there are more than one grid in a view. You can easily turn it off my using the IncludeNameInParameterAsPrefix to false when you have only one Grid in a view. Lets take a another quick look how to turn off the Name prefix:
<% Html.Telerik().Grid<InMemoryCustomer>()
.Name("MyGrid")
.Columns(
columns =>
{
columns.Add(c => c.Id);
columns.Add(c => c.Name);
columns.Add(c => c.Address);
columns.Add(c => c.RegisterAt).Format("{0:MM/dd/yyyy}");
columns.Add(c => c.IsActive).HeaderText("Active");
}
)
.SortMode(GridSortMode.MultiColumn)
.IncludeNameInParameterAsPrefix(false)
.Pager(pager => pager.PageSize(10).Style(GridPagerStyle.FirstPreviousNextLast))
.BindTo(Model)
.Render(); %>
(Check the line number 14 in the above snippet) Now, when you run the above code and click few of the column headers, it will get a similar picture like the following:
Now, you will see the urls are generated without the grid name prefix:
?orderBy=Name desc%2CRegisterAt asc&page=2 // Order By Name Descending, RegisterAt Ascending and Page 2
?orderBy=Address%20asc // Order by Address Ascending and Page 1
So far, we are using the Query String, What the about the routing? yes you can also use the routing instead of the old and ugly query string, but to use Routing you have define the route first, this is the reason, I have shown the query string examples first. Now, let me show you the routing example:
First we will define a route in global.asax like the following:
routes.MapRoute("PrettyUrl", "{controller}/PrettyUrl/{orderBy}/{page}", new { controller = "Grid", action = "PrettyUrl", orderBy = string.Empty, page = 1 });
Next, we will create an action method very similar to the above query string example, except, it now accepts the orderBy and page as argument:
public ActionResult PrettyUrl(string orderBy, int? page)
{
Random rnd = new Random();
IList<InMemoryCustomer> model = new List<InMemoryCustomer>();
for (int i = 1; i <= 100; i++)
{
InMemoryCustomer c = new InMemoryCustomer
{
Id = rnd.Next(1, 1000),
Name = string.Format("Dummy Name #{0}", i),
Address = string.Format("Dummy Address #{0}", i),
RegisterAt =
DateTime.Now.AddMonths(-rnd.Next(1, 48)).AddDays(-rnd.Next(0, 365)),
Balance = rnd.Next(1000, 10000),
IsActive = ((i%4) == 0)
};
model.Add(c);
}
return View(model);
}
And the view is exactly same as above:
<% Html.Telerik().Grid<InMemoryCustomer>()
.Name("MyGrid")
.Columns(
columns =>
{
columns.Add(c => c.Id);
columns.Add(c => c.Name);
columns.Add(c => c.Address);
columns.Add(c => c.RegisterAt).Format("{0:MM/dd/yyyy}");
columns.Add(c => c.IsActive).HeaderText("Active");
}
)
.SortMode(GridSortMode.MultiColumn)
.IncludeNameInParameterAsPrefix(false)
.Pager(pager => pager.PageSize(10).Style(GridPagerStyle.FirstPreviousNextLast))
.BindTo(Model)
.Render(); %>
Now when run it, the urls will appear like the following:
/Grid/PrettyUrl/Name asc,Address asc,RegisterAt asc/2
/Grid/PrettyUrl/Name desc,IsActive asc
IE will replace the spaces with Url encoded %20, If you have used the ADO.NET Data Service you already guess that we are following the same style for formatting order by clause as ADO.NET Data Service. The default value for orderBy and page parameters are same as there names, if your route is declared with some other names or you want to change the values for query string, use the following syntax (Check line 14 and 15):
<% Html.Telerik().Grid<InMemoryCustomer>()
.Name("MyGrid")
.Columns(
columns =>
{
columns.Add(c => c.Id);
columns.Add(c => c.Name);
columns.Add(c => c.Address);
columns.Add(c => c.RegisterAt).Format("{0:MM/dd/yyyy}");
columns.Add(c => c.IsActive).HeaderText("Active");
}
)
.SortMode(GridSortMode.MultiColumn)
.OrderByParameterName("sortBy")
.CurrentPageParameterName("p")
.Pager(pager => pager.PageSize(10).Style(GridPagerStyle.FirstPreviousNextLast))
.BindTo(Model)
.Render(); %>
Currently, the routing only works for single grid due to the limitation of the ASP.NET Routing, I will post more on this later on.
Before concluding the post, there are one more nice feature that I like to mention, if you are wondering how the above code is doing the auto paging and sorting, let me tell you that we are using the same DataEngine as our Wpf Control suite is using, the nice things about it that it has the complete support to propagate the arbitrary expressions to query providers, which means if you are using LinqToSQL, LinqToEntities, LinqToNHibernate or any database Linq provider then the actual processing will be done by database server rather than in memory operation. But, if want to take charges of this operations, you can certainly do it, just set the RequireProcessing to false.
This is a just the start, there are lot more features we will be adding before our final release, We will be posting the features as we develop to gather feedback from you, so please let us know what you like, what you do not like and how we can improve.
Thanks.
Filed under: Asp.net, MVC, ASPNETMVC, ASP.NET MVC, Open Source, Telerik