From 938d39aa0f4bf724183ce53f163732b445dd9fd3 Mon Sep 17 00:00:00 2001 From: Dan Miser Date: Wed, 1 Aug 2012 14:36:24 -0500 Subject: [PATCH 1/2] Make DataTableIncludes work with relative paths --- Mvc.JQuery.Datatables/DataTablesHelper.cs | 106 +++++++++++----------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/Mvc.JQuery.Datatables/DataTablesHelper.cs b/Mvc.JQuery.Datatables/DataTablesHelper.cs index 40eb0d2..141754a 100644 --- a/Mvc.JQuery.Datatables/DataTablesHelper.cs +++ b/Mvc.JQuery.Datatables/DataTablesHelper.cs @@ -1,54 +1,54 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using System.Web; -using System.Web.Mvc; -using System.Web.Mvc.Html; - -namespace Mvc.JQuery.Datatables -{ - public static class DataTablesHelper - { - - public static IHtmlString DataTableIncludes(this HtmlHelper helper, bool jqueryUi = false, bool filters = true, bool tableTools = true) - { - StringBuilder output = new StringBuilder(); - Action addJs = s => output.AppendLine(@""); - Action addCss = s => output.AppendLine(@""); - - addCss("/Content/DataTables-1.9.2/media/css/" + (jqueryUi ? ("jquery.dataTables_themeroller.css") : "jquery.dataTables.css")); - addJs("/Scripts/DataTables-1.9.2/media/js/jquery.dataTables.js"); - if (filters) addJs("/Scripts/jquery.dataTables.columnFilter.js"); - if (tableTools) - { - addJs("/Scripts/DataTables-1.9.2/extras/TableTools/media/js/ZeroClipboard.js"); - addJs("/Scripts/DataTables-1.9.2/extras/TableTools/media/js/TableTools.js"); - addCss("/Content/DataTables-1.9.2/extras/TableTools/media/css/TableTools.css"); - } - return helper.Raw(output.ToString()); - - } - - public static DataTableVm DataTableVm(this HtmlHelper html, string id, Expression>> exp, params Tuple[] columns) - { - if (columns == null || columns.Length == 0) - { - columns = typeof(TResult).GetProperties().Where(p => p.GetGetMethod() != null).Select(p => Tuple.Create(p.Name, p.PropertyType)).ToArray(); - } - - var mi = exp.MethodInfo(); - var controllerName = typeof(TController).Name; - controllerName = controllerName.Substring(0, controllerName.LastIndexOf("Controller")); - var urlHelper = new UrlHelper(html.ViewContext.RequestContext); - var ajaxUrl = urlHelper.Action(mi.Name, controllerName); - return new DataTableVm(id, ajaxUrl, columns); - } - - public static DataTableVm DataTableVm(this HtmlHelper html, string id, string ajaxUrl, params string[] columns) - { - return new DataTableVm(id, ajaxUrl, columns.Select(c => Tuple.Create(c, typeof(string)))); - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Web; +using System.Web.Mvc; +using System.Web.Mvc.Html; + +namespace Mvc.JQuery.Datatables +{ + public static class DataTablesHelper + { + + public static IHtmlString DataTableIncludes(this HtmlHelper helper, bool jqueryUi = false, bool filters = true, bool tableTools = true) + { + StringBuilder output = new StringBuilder(); + Action addJs = s => output.AppendLine(@""); + Action addCss = s => output.AppendLine(@""); + + addCss("~/Content/DataTables-1.9.2/media/css/" + (jqueryUi ? ("jquery.dataTables_themeroller.css") : "jquery.dataTables.css")); + addJs("~/Scripts/DataTables-1.9.2/media/js/jquery.dataTables.js"); + if (filters) addJs("~/Scripts/jquery.dataTables.columnFilter.js"); + if (tableTools) + { + addJs("~/Scripts/DataTables-1.9.2/extras/TableTools/media/js/ZeroClipboard.js"); + addJs("~/Scripts/DataTables-1.9.2/extras/TableTools/media/js/TableTools.js"); + addCss("~/Content/DataTables-1.9.2/extras/TableTools/media/css/TableTools.css"); + } + return helper.Raw(output.ToString()); + + } + + public static DataTableVm DataTableVm(this HtmlHelper html, string id, Expression>> exp, params Tuple[] columns) + { + if (columns == null || columns.Length == 0) + { + columns = typeof(TResult).GetProperties().Where(p => p.GetGetMethod() != null).Select(p => Tuple.Create(p.Name, p.PropertyType)).ToArray(); + } + + var mi = exp.MethodInfo(); + var controllerName = typeof(TController).Name; + controllerName = controllerName.Substring(0, controllerName.LastIndexOf("Controller")); + var urlHelper = new UrlHelper(html.ViewContext.RequestContext); + var ajaxUrl = urlHelper.Action(mi.Name, controllerName); + return new DataTableVm(id, ajaxUrl, columns); + } + + public static DataTableVm DataTableVm(this HtmlHelper html, string id, string ajaxUrl, params string[] columns) + { + return new DataTableVm(id, ajaxUrl, columns.Select(c => Tuple.Create(c, typeof(string)))); + } + } } \ No newline at end of file From 6c2091f2108f8eec59832b33b6a28ab22040a2d6 Mon Sep 17 00:00:00 2001 From: Dan Miser Date: Thu, 2 Aug 2012 10:50:46 -0500 Subject: [PATCH 2/2] Support aoColumnDefs This change emits aoColumnDefs based on the view model that we are rendering. For example: 1. [ScaffoldColumn(false) will apply bVisible: false to the column 2. [DisplayName("Title")] will apply sTitle: Title to the column 3. The sName property will always be set to allow for a more flexible client and server side decoupling I also changed the sample to demonstrate this, and clean up a few small issues like making files look in the virtual path instead of an absolute top-level path. --- .../Controllers/HomeController.cs | 214 ++--- .../Mvc.JQuery.Datatables.Example.csproj | 803 +++++++++--------- .../Views/Home/Index.cshtml | 134 +-- .../Views/Shared/_Layout.cshtml | 62 +- .../Views/Shared/DataTable.cshtml | 130 +-- Mvc.JQuery.Datatables.sln | 64 +- Mvc.JQuery.Datatables/DataTableVm.cs | 304 +++---- Mvc.JQuery.Datatables/DataTablesColumn.cs | 15 + Mvc.JQuery.Datatables/DataTablesFilter.cs | 418 ++++----- Mvc.JQuery.Datatables/DataTablesHelper.cs | 37 +- .../DataTablesModelBinder.cs | 73 +- Mvc.JQuery.Datatables/DataTablesParam.cs | 86 +- Mvc.JQuery.Datatables/DataTablesResult.cs | 254 +++--- .../Mvc.JQuery.Datatables.csproj | 274 +++--- 14 files changed, 1485 insertions(+), 1383 deletions(-) create mode 100644 Mvc.JQuery.Datatables/DataTablesColumn.cs diff --git a/Mvc.JQuery.Datatables.Example/Controllers/HomeController.cs b/Mvc.JQuery.Datatables.Example/Controllers/HomeController.cs index cd8f60e..0de311f 100644 --- a/Mvc.JQuery.Datatables.Example/Controllers/HomeController.cs +++ b/Mvc.JQuery.Datatables.Example/Controllers/HomeController.cs @@ -1,106 +1,110 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Web; -using System.Web.Mvc; - -namespace Mvc.JQuery.Datatables.Example.Controllers -{ - public class HomeController : Controller - { - private static List _users; - // - // GET: /Home/ - - public ActionResult Index() - { - return View(); - } - - public enum PositionTypes - { - Engineer, - Tester, - Manager - } - - public DataTablesResult GetUsers(DataTablesParam dataTableParam) - { - var users = Users().AsQueryable(); - - return DataTablesResult.Create(users, dataTableParam, user => new UserView() - { - Id = user.Id, - Name = new MvcHtmlString("" + user.Name +""), - Email = user.Email, - Position = user.Position == null ? "" : user.Position.ToString(), - Number = user.Number, - Hired = user.Hired - }); - } - public DataTablesResult GetUsersUntyped(DataTablesParam dataTableParam) - { - var users = Users(); - - return DataTablesResult.Create(users, dataTableParam); - } - - private static List Users() - { - var r = new Random(); - var domains = "gmail.com,yahoo.com,hotmail.com".Split(',').ToArray(); - - var positions = new List { null, PositionTypes.Engineer, PositionTypes.Tester, PositionTypes.Manager }; - return _users ?? (_users = new List - ( - Enumerable.Range(1, 100).Select(i => - new User() - { - Id = i, - Email = "user" + i + "@" + domains[i%domains.Length], - Name = r.Next(6) == 3 ? null : "User" + i, - Position = positions[i%positions.Count], - Number = (Numbers) r.Next(4), - Hired = DateTimeOffset.UtcNow.AddDays(-1 * 365 * 3 * r.NextDouble()) - }) - )); - } - } - - public enum Numbers - { - Zero, - One, - Two, - Three, - Four - } - public class User - { - public int Id { get; set; } - public string Name { get; set; } - public string Email { get; set; } - - public HomeController.PositionTypes? Position { get; set; } - - public DateTimeOffset Hired { get; set; } - - public Numbers Number { get; set; } - } - - public class UserView - { - public int Id { get; set; } - public MvcHtmlString Name { get; set; } - - public string Email { get; set; } - - public string Position { get; set; } - public DateTimeOffset Hired { get; set; } - - public Numbers Number { get; set; } - } - - +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Globalization; +using System.Linq; +using System.Web; +using System.Web.Mvc; + +namespace Mvc.JQuery.Datatables.Example.Controllers +{ + public class HomeController : Controller + { + private static List _users; + // + // GET: /Home/ + + public ActionResult Index() + { + return View(); + } + + public enum PositionTypes + { + Engineer, + Tester, + Manager + } + + public DataTablesResult GetUsers(DataTablesParam dataTableParam) + { + var users = Users().AsQueryable(); + + return DataTablesResult.Create(users, dataTableParam, user => new UserView() + { + Id = user.Id, + Name = new MvcHtmlString("" + user.Name +""), + Email = user.Email, + Position = user.Position == null ? "" : user.Position.ToString(), + Number = user.Number, + Hired = user.Hired + }); + } + public DataTablesResult GetUsersUntyped(DataTablesParam dataTableParam) + { + var users = Users(); + + return DataTablesResult.Create(users, dataTableParam); + } + + private static List Users() + { + var r = new Random(); + var domains = "gmail.com,yahoo.com,hotmail.com".Split(',').ToArray(); + + var positions = new List { null, PositionTypes.Engineer, PositionTypes.Tester, PositionTypes.Manager }; + return _users ?? (_users = new List + ( + Enumerable.Range(1, 100).Select(i => + new User() + { + Id = i, + Email = "user" + i + "@" + domains[i%domains.Length], + Name = r.Next(6) == 3 ? null : "User" + i, + Position = positions[i%positions.Count], + Number = (Numbers) r.Next(4), + Hired = DateTimeOffset.UtcNow.AddDays(-1 * 365 * 3 * r.NextDouble()) + }) + )); + } + } + + public enum Numbers + { + Zero, + One, + Two, + Three, + Four + } + public class User + { + public int Id { get; set; } + public string Name { get; set; } + public string Email { get; set; } + + public HomeController.PositionTypes? Position { get; set; } + + public DateTimeOffset Hired { get; set; } + + public Numbers Number { get; set; } + } + + public class UserView + { + [ScaffoldColumn(false)] + public int Id { get; set; } + [DisplayName("UserName")] + public MvcHtmlString Name { get; set; } + + public string Email { get; set; } + + public string Position { get; set; } + public DateTimeOffset Hired { get; set; } + + public Numbers Number { get; set; } + } + + } \ No newline at end of file diff --git a/Mvc.JQuery.Datatables.Example/Mvc.JQuery.Datatables.Example.csproj b/Mvc.JQuery.Datatables.Example/Mvc.JQuery.Datatables.Example.csproj index 96c0ff5..b2be9dd 100644 --- a/Mvc.JQuery.Datatables.Example/Mvc.JQuery.Datatables.Example.csproj +++ b/Mvc.JQuery.Datatables.Example/Mvc.JQuery.Datatables.Example.csproj @@ -1,392 +1,413 @@ - - - - Debug - AnyCPU - - - 2.0 - {476D3266-8699-4E89-A528-646C1235EEB1} - {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Mvc.JQuery.Datatables.Example - Mvc.JQuery.Datatables.Example - v4.0 - false - false - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - ..\packages\EmbeddedResourceVirtualPathProvider.1.2.5\lib\net40\EmbeddedResourceVirtualPathProvider.dll - - - True - ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - - - - - - - - - - - - - - - - - - - - - - - - ..\packages\WebActivator.1.5\lib\net40\WebActivator.dll - - - - - - - - Global.asax - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Web.config - - - Web.config - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {389ADE94-7C32-4885-812E-68A2A74C82D8} - Mvc.JQuery.Datatables - - - - - - - - - - - - - - - - - - - - - - - - - - False - True - 50564 - / - - - False - False - - - False - - - - + + + + + Debug + AnyCPU + + + 2.0 + {476D3266-8699-4E89-A528-646C1235EEB1} + {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Mvc.JQuery.Datatables.Example + Mvc.JQuery.Datatables.Example + v4.0 + false + false + + + + + 4.0 + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + ..\packages\EmbeddedResourceVirtualPathProvider.1.2.5\lib\net40\EmbeddedResourceVirtualPathProvider.dll + + + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + + False + + + False + + + False + + + + + + + + + + + + + + + + + + + + + + ..\packages\WebActivator.1.5\lib\net40\WebActivator.dll + + + + + + + + Global.asax + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Web.config + + + Web.config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {389ADE94-7C32-4885-812E-68A2A74C82D8} + Mvc.JQuery.Datatables + + + + + + + + + + + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + + + + + False + False + 50564 + / + + + False + False + + + False + + + + \ No newline at end of file diff --git a/Mvc.JQuery.Datatables.Example/Views/Home/Index.cshtml b/Mvc.JQuery.Datatables.Example/Views/Home/Index.cshtml index 98dab9a..4d5e21f 100644 --- a/Mvc.JQuery.Datatables.Example/Views/Home/Index.cshtml +++ b/Mvc.JQuery.Datatables.Example/Views/Home/Index.cshtml @@ -1,67 +1,67 @@ -@{ - ViewBag.Title = "title"; -} -@Html.DataTableIncludes(jqueryUi:false) - - - -

Strongly typed datatable example

-
-Nuget install-package Mvc.JQuery.Datatables
-
-

- In the controller: -

-
-public IDataTablesResult<UserView> GetUsers(DataTablesParam dataTableParam)
-{
-    var users = new List<User>
-    (
-        Enumerable.Range(1, 100).Select(i => new User(){Id = i, Email = "user" + i + "@@gmail.com", Name = "User" + i})
-    ).AsQueryable();
-
-    return DataTablesResult.Create(users, dataTableParam, user => new UserView()
-    {
-        Id = user.Id,
-        Name = user.Name
-    });
-}
-
- -

-and in the view... - -

-@@using Mvc.JQuery.Datatables
-@@using Mvc.JQuery.Datatables.Example.Controllers
-
-<link type="text/css" href="@@Url.Content("~/Content/DataTables-1.8.2/media/css/demo_table.css")" rel="stylesheet"/>
-<script src="@@Url.Content("~/Scripts/DataTables-1.8.2/media/js/jquery.dataTables.js")" type="text/javascript"></script>
-
-@@Html.Partial("DataTable", Html.DataTableVm("table-id", (HomeController h) => h.GetUsers(null)))
-
-can also use 
-
-@@Html.Partial("DataTable", Html.DataTableVm("table-id", "/home/getusers", "Id", "Name", "Email"))
-
-

- -

Voila

- - -@using Mvc.JQuery.Datatables -@using Mvc.JQuery.Datatables.Example.Controllers -@{ - var vm = Html.DataTableVm("table-id", (HomeController h) => h.GetUsers(null)); - vm.FilterOn("Position").Select("Engineer", "Tester", "Manager") - .FilterOn("Id").NumberRange(); -} -@Html.Partial("DataTable", vm) - - - - - - - - +@{ + ViewBag.Title = "title"; +} + +@Html.DataTableIncludes(jqueryUi:false) + + + +

Strongly typed datatable example

+
+Nuget install-package Mvc.JQuery.Datatables
+
+

+ In the controller: +

+
+public DataTablesResult<UserView> GetUsers(DataTablesParam dataTableParam)
+{
+    var users = new List<User>
+    (
+        Enumerable.Range(1, 100).Select(i => new User(){Id = i, Email = "user" + i + "@@gmail.com", Name = "User" + i})
+    ).AsQueryable();
+
+    return DataTablesResult.Create(users, dataTableParam, user => new UserView()
+    {
+        Id = user.Id,
+        Name = user.Name
+    });
+}
+
+ +

+and in the view... + +

+@@Html.DataTableIncludes(jqueryUi:false)
+
+ ...
+
+@@using Mvc.JQuery.Datatables
+@@using Mvc.JQuery.Datatables.Example.Controllers
+
+@@Html.Partial("DataTable", Html.DataTableVm("table-id", (HomeController h) => h.GetUsers(null)))
+
+you can also use 
+
+@@Html.Partial("DataTable", Html.DataTableVm("table-id", "/home/getusers", "Id", "Name", "Email"))
+
+

+ +

Voila

+@using Mvc.JQuery.Datatables +@using Mvc.JQuery.Datatables.Example.Controllers +@{ + var vm = Html.DataTableVm("table-id", (HomeController h) => h.GetUsers(null)); + vm.FilterOn("Position").Select("Engineer", "Tester", "Manager") + .FilterOn("Id").NumberRange(); +} +@Html.Partial("DataTable", vm) + + + + + + + + diff --git a/Mvc.JQuery.Datatables.Example/Views/Shared/_Layout.cshtml b/Mvc.JQuery.Datatables.Example/Views/Shared/_Layout.cshtml index 779fae3..ac7f42e 100644 --- a/Mvc.JQuery.Datatables.Example/Views/Shared/_Layout.cshtml +++ b/Mvc.JQuery.Datatables.Example/Views/Shared/_Layout.cshtml @@ -1,31 +1,31 @@ - - - - - @ViewBag.Title - - - - - - - - -
-
-
-

@Html.ActionLink("My MVC Application", "Index", "Home")

- - @Html.Partial("_LogOnPartial") -
-
-
-
- @RenderBody() -
-
-
- - + + + + + @ViewBag.Title + + + + + + + + +
+
+
+

@Html.ActionLink("My MVC Application", "Index", "Home")

+ + @Html.Partial("_LogOnPartial") +
+
+
+
+ @RenderBody() +
+
+
+ + diff --git a/Mvc.JQuery.Datatables.Templates/Views/Shared/DataTable.cshtml b/Mvc.JQuery.Datatables.Templates/Views/Shared/DataTable.cshtml index fa380a2..a26f090 100644 --- a/Mvc.JQuery.Datatables.Templates/Views/Shared/DataTable.cshtml +++ b/Mvc.JQuery.Datatables.Templates/Views/Shared/DataTable.cshtml @@ -1,64 +1,66 @@ -@using Mvc.JQuery.Datatables -@model DataTableVm -@{ - -} - - - - @foreach (var column in Model.Columns) - { - - } - - @if (Model.ColumnFilter) - { - - @foreach (var column in Model.Columns) - { - - } - - } - - - - - - -
@column.Item1
@column.Item1
- Loading data from server -
- +@using Mvc.JQuery.Datatables +@model DataTableVm +@{ + +} + + + + @foreach (var column in Model.Columns) + { + + } + + @if (Model.ColumnFilter) + { + + @foreach (var column in Model.Columns) + { + + } + + } + + + + + + +
@column.Item1
@column.Item1
+ Loading data from server +
+ diff --git a/Mvc.JQuery.Datatables.sln b/Mvc.JQuery.Datatables.sln index 01f0a12..87aa078 100644 --- a/Mvc.JQuery.Datatables.sln +++ b/Mvc.JQuery.Datatables.sln @@ -1,32 +1,32 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mvc.JQuery.Datatables", "Mvc.JQuery.Datatables\Mvc.JQuery.Datatables.csproj", "{389ADE94-7C32-4885-812E-68A2A74C82D8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mvc.JQuery.Datatables.Example", "Mvc.JQuery.Datatables.Example\Mvc.JQuery.Datatables.Example.csproj", "{476D3266-8699-4E89-A528-646C1235EEB1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mvc.JQuery.Datatables.Templates", "Mvc.JQuery.Datatables.Templates\Mvc.JQuery.Datatables.Templates.csproj", "{8DA3D5E6-D714-40C3-B6CB-E88D852C5175}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {389ADE94-7C32-4885-812E-68A2A74C82D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {389ADE94-7C32-4885-812E-68A2A74C82D8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {389ADE94-7C32-4885-812E-68A2A74C82D8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {389ADE94-7C32-4885-812E-68A2A74C82D8}.Release|Any CPU.Build.0 = Release|Any CPU - {476D3266-8699-4E89-A528-646C1235EEB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {476D3266-8699-4E89-A528-646C1235EEB1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {476D3266-8699-4E89-A528-646C1235EEB1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {476D3266-8699-4E89-A528-646C1235EEB1}.Release|Any CPU.Build.0 = Release|Any CPU - {8DA3D5E6-D714-40C3-B6CB-E88D852C5175}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8DA3D5E6-D714-40C3-B6CB-E88D852C5175}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8DA3D5E6-D714-40C3-B6CB-E88D852C5175}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8DA3D5E6-D714-40C3-B6CB-E88D852C5175}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mvc.JQuery.Datatables", "Mvc.JQuery.Datatables\Mvc.JQuery.Datatables.csproj", "{389ADE94-7C32-4885-812E-68A2A74C82D8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mvc.JQuery.Datatables.Example", "Mvc.JQuery.Datatables.Example\Mvc.JQuery.Datatables.Example.csproj", "{476D3266-8699-4E89-A528-646C1235EEB1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mvc.JQuery.Datatables.Templates", "Mvc.JQuery.Datatables.Templates\Mvc.JQuery.Datatables.Templates.csproj", "{8DA3D5E6-D714-40C3-B6CB-E88D852C5175}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {389ADE94-7C32-4885-812E-68A2A74C82D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {389ADE94-7C32-4885-812E-68A2A74C82D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {389ADE94-7C32-4885-812E-68A2A74C82D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {389ADE94-7C32-4885-812E-68A2A74C82D8}.Release|Any CPU.Build.0 = Release|Any CPU + {476D3266-8699-4E89-A528-646C1235EEB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {476D3266-8699-4E89-A528-646C1235EEB1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {476D3266-8699-4E89-A528-646C1235EEB1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {476D3266-8699-4E89-A528-646C1235EEB1}.Release|Any CPU.Build.0 = Release|Any CPU + {8DA3D5E6-D714-40C3-B6CB-E88D852C5175}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DA3D5E6-D714-40C3-B6CB-E88D852C5175}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DA3D5E6-D714-40C3-B6CB-E88D852C5175}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DA3D5E6-D714-40C3-B6CB-E88D852C5175}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Mvc.JQuery.Datatables/DataTableVm.cs b/Mvc.JQuery.Datatables/DataTableVm.cs index a3c27be..a7ccef3 100644 --- a/Mvc.JQuery.Datatables/DataTableVm.cs +++ b/Mvc.JQuery.Datatables/DataTableVm.cs @@ -1,144 +1,162 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Mvc.JQuery.Datatables -{ - public class DataTableVm - { - static DataTableVm() - { - DefaultTableClass = "table table-bordered table-striped"; - } - - public static string DefaultTableClass { get; set; } - public string TableClass { get; set; } - - public DataTableVm(string id, string ajaxUrl, IEnumerable> columns) - { - AjaxUrl = ajaxUrl; - this.Id = id; - this.Columns = columns; - FilterTypeRules = new FilterRuleList(); - FilterTypeRules.AddRange(StaticFilterTypeRules); - this.ShowSearch = true; - this.ShowPageSizes = true; - this.TableTools = true; - } - - public bool ShowSearch { get; set; } - - public string Id { get; private set; } - - public string AjaxUrl { get; private set; } - - public IEnumerable> Columns { get; private set; } - - public bool ColumnFilter { get; set; } - - public bool TableTools { get; set; } - - public bool AutoWidth { get; set; } - - public string ColumnFiltersString - { - get { return string.Join(",", Columns.Select(c => GetFilterType(c.Item1, c.Item2))); } - } - - public string Dom - { - get { - var sdom = ""; - if (TableTools) sdom += "T<\"clear\">"; - if (ShowPageSizes) sdom += "l"; - if (ShowSearch) sdom += "f"; - sdom += "tipr"; - return sdom; - } - } - - public bool ShowPageSizes { get; set; } - - - public string GetFilterType(string columnName, Type type) - { - foreach (Func filterTypeRule in FilterTypeRules) - { - var rule = filterTypeRule(columnName, type); - if (rule != null) return rule; - } - return "null"; - } - - public FilterRuleList FilterTypeRules; - - public static FilterRuleList StaticFilterTypeRules = new FilterRuleList() - { - (c, t) => (DateTypes.Contains(t)) ? "{type: 'date-range'}" : null, - (c, t) => "{type: 'text'}", //by default, text filter on everything - }; - - private static List DateTypes = new List { typeof(DateTime), typeof(DateTime?), typeof(DateTimeOffset), typeof(DateTimeOffset?) }; - - public class _FilterOn - { - private readonly TTarget _target; - private readonly FilterRuleList _list; - private readonly Func _predicate; - - public _FilterOn(TTarget target, FilterRuleList list, Func predicate) - { - _target = target; - _list = list; - _predicate = predicate; - } - - public TTarget Select(params string[] options) - { - AddRule("{type: 'select', values: ['" + string.Join("','", options) + "']}"); - return _target; - } - public TTarget NumberRange() - { - AddRule("{type: 'number-range'}"); - return _target; - } - - public TTarget DateRange() - { - AddRule("{type: 'date-range'}"); - return _target; - } - - public TTarget Number() - { - AddRule("{type: 'number'}"); - return _target; - } - - public TTarget None() - { - AddRule("null"); - return _target; - } - - private void AddRule(string result) - { - _list.Insert(0, (c, t) => _predicate(c, t) ? result : null); - } - } - public _FilterOn FilterOn() - { - return new _FilterOn(this, this.FilterTypeRules, (c, t) => t == typeof(T)); - } - public _FilterOn FilterOn(string columnName) - { - return new _FilterOn(this, this.FilterTypeRules, (c, t) => c == columnName); - } - - } - public class FilterRuleList : List> - { - - } +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Mvc.JQuery.Datatables +{ + public class DataTableVm + { + static DataTableVm() + { + DefaultTableClass = "table table-bordered table-striped"; + } + + public static string DefaultTableClass { get; set; } + public string TableClass { get; set; } + + public DataTableVm(string id, string ajaxUrl, IEnumerable> columns) + { + AjaxUrl = ajaxUrl; + this.Id = id; + this.Columns = columns; + FilterTypeRules = new FilterRuleList(); + FilterTypeRules.AddRange(StaticFilterTypeRules); + this.ShowSearch = true; + this.ShowPageSizes = true; + this.TableTools = true; + } + + public bool ShowSearch { get; set; } + + public string Id { get; private set; } + + public string AjaxUrl { get; private set; } + + public IEnumerable> Columns { get; private set; } + + public bool ColumnFilter { get; set; } + + public bool TableTools { get; set; } + + public bool AutoWidth { get; set; } + + public string ColumnFiltersString + { + get { return string.Join(",", Columns.Select(c => GetFilterType(c.Item1, c.Item2.Type))); } + } + + public string ColumnDefs + { + get + { + string s = "["; + for (int i = 0; i < Columns.Count(); i++ ) + { + var col = Columns.ElementAt(i); + s += string.Format("{{ \"sName\": \"{0}\", \"sTitle\": \"{1}\", \"bVisible\": {2}, \"aTargets\": [{3}]}}", col.Item1, col.Item2.Title, col.Item2.Visible.ToString().ToLowerInvariant(), i); + if (i < Columns.Count() - 1) + s += ", "; + } + + s += "]"; + return s; + } + } + + public string Dom + { + get { + var sdom = ""; + if (TableTools) sdom += "T<\"clear\">"; + if (ShowPageSizes) sdom += "l"; + if (ShowSearch) sdom += "f"; + sdom += "tipr"; + return sdom; + } + } + + public bool ShowPageSizes { get; set; } + + + public string GetFilterType(string columnName, Type type) + { + foreach (Func filterTypeRule in FilterTypeRules) + { + var rule = filterTypeRule(columnName, type); + if (rule != null) return rule; + } + return "null"; + } + + public FilterRuleList FilterTypeRules; + + public static FilterRuleList StaticFilterTypeRules = new FilterRuleList() + { + (c, t) => (DateTypes.Contains(t)) ? "{type: 'date-range'}" : null, + (c, t) => "{type: 'text'}", //by default, text filter on everything + }; + + private static List DateTypes = new List { typeof(DateTime), typeof(DateTime?), typeof(DateTimeOffset), typeof(DateTimeOffset?) }; + + public class _FilterOn + { + private readonly TTarget _target; + private readonly FilterRuleList _list; + private readonly Func _predicate; + + public _FilterOn(TTarget target, FilterRuleList list, Func predicate) + { + _target = target; + _list = list; + _predicate = predicate; + } + + public TTarget Select(params string[] options) + { + AddRule("{type: 'select', values: ['" + string.Join("','", options) + "']}"); + return _target; + } + public TTarget NumberRange() + { + AddRule("{type: 'number-range'}"); + return _target; + } + + public TTarget DateRange() + { + AddRule("{type: 'date-range'}"); + return _target; + } + + public TTarget Number() + { + AddRule("{type: 'number'}"); + return _target; + } + + public TTarget None() + { + AddRule("null"); + return _target; + } + + private void AddRule(string result) + { + _list.Insert(0, (c, t) => _predicate(c, t) ? result : null); + } + } + public _FilterOn FilterOn() + { + return new _FilterOn(this, this.FilterTypeRules, (c, t) => t == typeof(T)); + } + public _FilterOn FilterOn(string columnName) + { + return new _FilterOn(this, this.FilterTypeRules, (c, t) => c == columnName); + } + + } + public class FilterRuleList : List> + { + + } } \ No newline at end of file diff --git a/Mvc.JQuery.Datatables/DataTablesColumn.cs b/Mvc.JQuery.Datatables/DataTablesColumn.cs new file mode 100644 index 0000000..acd2ef3 --- /dev/null +++ b/Mvc.JQuery.Datatables/DataTablesColumn.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Mvc.JQuery.Datatables +{ + public class DataTablesColumn + { + public Type Type { get; set; } + public string Name { get; set; } + public string Title { get; set; } + public bool Visible { get; set; } + } +} diff --git a/Mvc.JQuery.Datatables/DataTablesFilter.cs b/Mvc.JQuery.Datatables/DataTablesFilter.cs index 6d70b67..6a7a159 100644 --- a/Mvc.JQuery.Datatables/DataTablesFilter.cs +++ b/Mvc.JQuery.Datatables/DataTablesFilter.cs @@ -1,210 +1,210 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Mvc.JQuery.Datatables.DynamicLinq; - -namespace Mvc.JQuery.Datatables -{ - public class DataTablesFilter - { - public IQueryable FilterPagingSortingSearch(DataTablesParam dtParameters, IQueryable data, out int totalRecordsDisplay, Tuple[] columns) - { - if (!String.IsNullOrEmpty(dtParameters.sSearch)) - { - var parts = new List(); - var parameters = new List(); - for (var i = 0; i < dtParameters.iColumns; i++) - { - if (dtParameters.bSearchable[i]) - { - parts.Add(GetFilterClause(dtParameters.sSearch, columns[i], parameters)); - } - } - data = data.Where(string.Join(" or ", parts), parameters.ToArray()); - } - for (int i = 0; i < dtParameters.sSearchColumns.Count; i++) - { - if (dtParameters.bSearchable[i]) - { - var searchColumn = dtParameters.sSearchColumns[i]; - if (!string.IsNullOrWhiteSpace(searchColumn)) - { - var parameters = new List(); - var filterClause = GetFilterClause(dtParameters.sSearchColumns[i], columns[i], parameters); - data = data.Where(filterClause, parameters.ToArray()); - } - } - } - string sortString = ""; - for (int i = 0; i < dtParameters.iSortingCols; i++) - { - - int columnNumber = dtParameters.iSortCol[i]; - string columnName = columns[columnNumber].Item1; - string sortDir = dtParameters.sSortDir[i]; - if (i != 0) - sortString += ", "; - sortString += columnName + " " + sortDir; - } - - totalRecordsDisplay = data.Count(); - - data = data.OrderBy(sortString); - data = data.Skip(dtParameters.iDisplayStart); - if (dtParameters.iDisplayLength > -1) - { - data = data.Take(dtParameters.iDisplayLength); - } - - return data; - } - - public delegate string ReturnedFilteredQueryForType(string query, string columnName, Type columnType, List parametersForLinqQuery); - - static string FilterMethod(string q) - { - if (q.StartsWith("^")) - { - return "ToLower().StartsWith(\"" + q.ToLower().Substring(1).Replace("\"", "\"\"") + "\")"; - } - else - { - return "ToLower().Contains(\"" + q.ToLower().Replace("\"", "\"\"") + "\")"; - } - } - - static readonly List Filters = new List() - { - Guard(IsDateType, DateFilter), - Guard(IsNumericType, NumericFilter) - - }; - - private static bool Is(Type arg) - { - return arg is T; - } - - private static string NumericFilter(string query, string columnname, Type columnType, List parametersForLinqQuery) - { - if (query.Contains("~")) - { - var parts = query.Split('~'); - var clause = null as string; - try - { - parametersForLinqQuery.Add(Convert.ChangeType(parts[0], columnType)); - clause = string.Format("{0} >= @{1}", columnname, parametersForLinqQuery.Count - 1); - } - catch (FormatException) - { - } - - try - { - parametersForLinqQuery.Add(Convert.ChangeType(parts[1], columnType)); - if (clause != null) clause += " and "; - clause += string.Format("{0} <= @{1}", columnname, parametersForLinqQuery.Count - 1); - } - catch (FormatException) - { - } - return clause ?? "true" ; - - } - else - { - return string.Format("({1} == null ? \"\" : {1}.ToString()).{0}", FilterMethod(query), columnname); - } - } - - private static string DateFilter(string query, string columnname, Type columnType, List parametersForLinqQuery) - { - if (query.Contains("~")) - { - var parts = query.Split('~'); - DateTimeOffset start, end; - DateTimeOffset.TryParse(parts[0] ?? "", out start); - if (!DateTimeOffset.TryParse(parts[1] ?? "", out end)) end = DateTimeOffset.MaxValue; - - parametersForLinqQuery.Add(start); - parametersForLinqQuery.Add(end); - return string.Format("{0}.Ticks >= @{1}.Ticks and {0}.Ticks <= @{2}.Ticks", columnname, parametersForLinqQuery.Count - 2, parametersForLinqQuery.Count - 1); - } - else - { - return string.Format("{1}.ToLocalTime().ToString(\"g\").{0}", FilterMethod(query), columnname); - } - } - - public delegate string GuardedFilter(string query, string columnName, Type columnType, List parametersForLinqQuery); - - static ReturnedFilteredQueryForType Guard(Func guard, GuardedFilter filter) - { - return (q, c, t, p) => - { - if (!guard(t)) - { - return null; - } - return filter(q, c, t, p); - }; - } - - public static void RegisterFilter(GuardedFilter filter) - { - Filters.Add(Guard(Is, filter)); - } - - private static string GetFilterClause(string query, Tuple column, List parametersForLinqQuery) - { - foreach (var filter in Filters) - { - var filteredQuery = filter(query, column.Item1, column.Item2, parametersForLinqQuery); - if (filteredQuery != null) - { - return filteredQuery; - } - } - var parts = query.Split('~').Select(q => string.Format("({1} == null ? \"\" : {1}.ToString()).{0}", FilterMethod(q), column.Item1)); - return "(" + string.Join(") OR (", parts) + ")"; - } - - public static bool IsNumericType(Type type) - { - if (type == null || type.IsEnum) - { - return false; - } - - switch (Type.GetTypeCode(type)) - { - case TypeCode.Byte: - case TypeCode.Decimal: - case TypeCode.Double: - case TypeCode.Int16: - case TypeCode.Int32: - case TypeCode.Int64: - case TypeCode.SByte: - case TypeCode.Single: - case TypeCode.UInt16: - case TypeCode.UInt32: - case TypeCode.UInt64: - return true; - case TypeCode.Object: - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - return IsNumericType(Nullable.GetUnderlyingType(type)); - } - return false; - } - return false; - - } - public static bool IsDateType(Type type) - { - return type == typeof(DateTime) || type == typeof(DateTimeOffset) || type == typeof(DateTime?) || type == typeof(DateTimeOffset?); - } - - } +using System; +using System.Collections.Generic; +using System.Linq; +using Mvc.JQuery.Datatables.DynamicLinq; + +namespace Mvc.JQuery.Datatables +{ + public class DataTablesFilter + { + public IQueryable FilterPagingSortingSearch(DataTablesParam dtParameters, IQueryable data, out int totalRecordsDisplay, Tuple[] columns) + { + if (!String.IsNullOrEmpty(dtParameters.sSearch)) + { + var parts = new List(); + var parameters = new List(); + for (var i = 0; i < dtParameters.iColumns; i++) + { + if (dtParameters.bSearchable[i]) + { + parts.Add(GetFilterClause(dtParameters.sSearch, columns[i], parameters)); + } + } + data = data.Where(string.Join(" or ", parts), parameters.ToArray()); + } + for (int i = 0; i < dtParameters.sSearchColumns.Count; i++) + { + if (dtParameters.bSearchable[i]) + { + var searchColumn = dtParameters.sSearchColumns[i]; + if (!string.IsNullOrWhiteSpace(searchColumn)) + { + var parameters = new List(); + var filterClause = GetFilterClause(dtParameters.sSearchColumns[i], columns[i], parameters); + data = data.Where(filterClause, parameters.ToArray()); + } + } + } + string sortString = ""; + for (int i = 0; i < dtParameters.iSortingCols; i++) + { + + int columnNumber = dtParameters.iSortCol[i]; + string columnName = columns[columnNumber].Item1; + string sortDir = dtParameters.sSortDir[i]; + if (i != 0) + sortString += ", "; + sortString += columnName + " " + sortDir; + } + + totalRecordsDisplay = data.Count(); + + data = data.OrderBy(sortString); + data = data.Skip(dtParameters.iDisplayStart); + if (dtParameters.iDisplayLength > -1) + { + data = data.Take(dtParameters.iDisplayLength); + } + + return data; + } + + public delegate string ReturnedFilteredQueryForType(string query, string columnName, Type columnType, List parametersForLinqQuery); + + static string FilterMethod(string q) + { + if (q.StartsWith("^")) + { + return "ToLower().StartsWith(\"" + q.ToLower().Substring(1).Replace("\"", "\"\"") + "\")"; + } + else + { + return "ToLower().Contains(\"" + q.ToLower().Replace("\"", "\"\"") + "\")"; + } + } + + static readonly List Filters = new List() + { + Guard(IsDateType, DateFilter), + Guard(IsNumericType, NumericFilter) + + }; + + private static bool Is(Type arg) + { + return arg is T; + } + + private static string NumericFilter(string query, string columnname, Type columnType, List parametersForLinqQuery) + { + if (query.Contains("~")) + { + var parts = query.Split('~'); + var clause = null as string; + try + { + parametersForLinqQuery.Add(Convert.ChangeType(parts[0], columnType)); + clause = string.Format("{0} >= @{1}", columnname, parametersForLinqQuery.Count - 1); + } + catch (FormatException) + { + } + + try + { + parametersForLinqQuery.Add(Convert.ChangeType(parts[1], columnType)); + if (clause != null) clause += " and "; + clause += string.Format("{0} <= @{1}", columnname, parametersForLinqQuery.Count - 1); + } + catch (FormatException) + { + } + return clause ?? "true" ; + + } + else + { + return string.Format("({1} == null ? \"\" : {1}.ToString()).{0}", FilterMethod(query), columnname); + } + } + + private static string DateFilter(string query, string columnname, Type columnType, List parametersForLinqQuery) + { + if (query.Contains("~")) + { + var parts = query.Split('~'); + DateTimeOffset start, end; + DateTimeOffset.TryParse(parts[0] ?? "", out start); + if (!DateTimeOffset.TryParse(parts[1] ?? "", out end)) end = DateTimeOffset.MaxValue; + + parametersForLinqQuery.Add(start); + parametersForLinqQuery.Add(end); + return string.Format("{0}.Ticks >= @{1}.Ticks and {0}.Ticks <= @{2}.Ticks", columnname, parametersForLinqQuery.Count - 2, parametersForLinqQuery.Count - 1); + } + else + { + return string.Format("{1}.ToLocalTime().ToString(\"g\").{0}", FilterMethod(query), columnname); + } + } + + public delegate string GuardedFilter(string query, string columnName, Type columnType, List parametersForLinqQuery); + + static ReturnedFilteredQueryForType Guard(Func guard, GuardedFilter filter) + { + return (q, c, t, p) => + { + if (!guard(t)) + { + return null; + } + return filter(q, c, t, p); + }; + } + + public static void RegisterFilter(GuardedFilter filter) + { + Filters.Add(Guard(Is, filter)); + } + + private static string GetFilterClause(string query, Tuple column, List parametersForLinqQuery) + { + foreach (var filter in Filters) + { + var filteredQuery = filter(query, column.Item1, column.Item2.Type, parametersForLinqQuery); + if (filteredQuery != null) + { + return filteredQuery; + } + } + var parts = query.Split('~').Select(q => string.Format("({1} == null ? \"\" : {1}.ToString()).{0}", FilterMethod(q), column.Item1)); + return "(" + string.Join(") OR (", parts) + ")"; + } + + public static bool IsNumericType(Type type) + { + if (type == null || type.IsEnum) + { + return false; + } + + switch (Type.GetTypeCode(type)) + { + case TypeCode.Byte: + case TypeCode.Decimal: + case TypeCode.Double: + case TypeCode.Int16: + case TypeCode.Int32: + case TypeCode.Int64: + case TypeCode.SByte: + case TypeCode.Single: + case TypeCode.UInt16: + case TypeCode.UInt32: + case TypeCode.UInt64: + return true; + case TypeCode.Object: + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + return IsNumericType(Nullable.GetUnderlyingType(type)); + } + return false; + } + return false; + + } + public static bool IsDateType(Type type) + { + return type == typeof(DateTime) || type == typeof(DateTimeOffset) || type == typeof(DateTime?) || type == typeof(DateTimeOffset?); + } + + } } \ No newline at end of file diff --git a/Mvc.JQuery.Datatables/DataTablesHelper.cs b/Mvc.JQuery.Datatables/DataTablesHelper.cs index 141754a..26c2f39 100644 --- a/Mvc.JQuery.Datatables/DataTablesHelper.cs +++ b/Mvc.JQuery.Datatables/DataTablesHelper.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Linq.Expressions; using System.Text; @@ -31,11 +33,11 @@ public static IHtmlString DataTableIncludes(this HtmlHelper helper, bool jqueryU } - public static DataTableVm DataTableVm(this HtmlHelper html, string id, Expression>> exp, params Tuple[] columns) + public static DataTableVm DataTableVm(this HtmlHelper html, string id, Expression>> exp, params Tuple[] columns) { if (columns == null || columns.Length == 0) { - columns = typeof(TResult).GetProperties().Where(p => p.GetGetMethod() != null).Select(p => Tuple.Create(p.Name, p.PropertyType)).ToArray(); + columns = BuildColumns(); } var mi = exp.MethodInfo(); @@ -46,9 +48,38 @@ public static DataTableVm DataTableVm(this HtmlHelper html return new DataTableVm(id, ajaxUrl, columns); } + public static Tuple[] BuildColumns() + { + var props = + typeof (TResult).GetProperties() + .Where(p => p.GetGetMethod() != null) + .Select(p => p); + var propCount = props.Count(); + var columns = new Tuple[propCount]; + + for (int i = 0; i < propCount; i++) + { + var prop = props.ElementAt(i); + var col = new DataTablesColumn {Type = prop.PropertyType, Name = prop.Name, Visible = true}; + + var displayNameAttribute = prop.GetCustomAttributes(typeof (DisplayNameAttribute), false); + col.Title = displayNameAttribute.Length > 0 + ? ((DisplayNameAttribute) displayNameAttribute[0]).DisplayName + : prop.Name; + + var scaffoldColumnAttribute = prop.GetCustomAttributes(typeof (ScaffoldColumnAttribute), false); + if (scaffoldColumnAttribute.Length > 0) + col.Visible = ((ScaffoldColumnAttribute) scaffoldColumnAttribute[0]).Scaffold; + + columns[i] = Tuple.Create(prop.Name, col); + } + + return columns; + } + public static DataTableVm DataTableVm(this HtmlHelper html, string id, string ajaxUrl, params string[] columns) { - return new DataTableVm(id, ajaxUrl, columns.Select(c => Tuple.Create(c, typeof(string)))); + return new DataTableVm(id, ajaxUrl, columns.Select(c => Tuple.Create(c, new DataTablesColumn { Type = typeof(string), Name = c, Title = c, Visible = true}))); } } } \ No newline at end of file diff --git a/Mvc.JQuery.Datatables/DataTablesModelBinder.cs b/Mvc.JQuery.Datatables/DataTablesModelBinder.cs index 24ab96c..abd8a68 100644 --- a/Mvc.JQuery.Datatables/DataTablesModelBinder.cs +++ b/Mvc.JQuery.Datatables/DataTablesModelBinder.cs @@ -1,36 +1,39 @@ -using System; -using System.Web.Mvc; - -namespace Mvc.JQuery.Datatables -{ - /// - /// Model binder for datatables.js parameters a la http://geeksprogramando.blogspot.com/2011/02/jquery-datatables-plug-in-with-asp-mvc.html - /// - public class DataTablesModelBinder : IModelBinder - { - public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) - { - DataTablesParam obj = new DataTablesParam(); - var request = controllerContext.HttpContext.Request.Params; - - obj.iDisplayStart = Convert.ToInt32(request["iDisplayStart"]); - obj.iDisplayLength = Convert.ToInt32(request["iDisplayLength"]); - obj.iColumns = Convert.ToInt32(request["iColumns"]); - obj.sSearch = request["sSearch"]; - obj.bEscapeRegex = Convert.ToBoolean(request["bEscapeRegex"]); - obj.iSortingCols = Convert.ToInt32(request["iSortingCols"]); - obj.sEcho = int.Parse(request["sEcho"]); - - for (int i = 0; i < obj.iColumns; i++) - { - obj.bSortable.Add(Convert.ToBoolean(request["bSortable_" + i])); - obj.bSearchable.Add(Convert.ToBoolean(request["bSearchable_" + i])); - obj.sSearchColumns.Add(request["sSearch_" + i]); - obj.bEscapeRegexColumns.Add(Convert.ToBoolean(request["bEscapeRegex_" + i])); - obj.iSortCol.Add(Convert.ToInt32(request["iSortCol_" + i])); - obj.sSortDir.Add(request["sSortDir_" + i]); - } - return obj; - } - } +using System; +using System.Web.Mvc; + +namespace Mvc.JQuery.Datatables +{ + /// + /// Model binder for datatables.js parameters a la http://geeksprogramando.blogspot.com/2011/02/jquery-datatables-plug-in-with-asp-mvc.html + /// + public class DataTablesModelBinder : IModelBinder + { + public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) + { + DataTablesParam obj = new DataTablesParam(); + var request = controllerContext.HttpContext.Request.Params; + + obj.iDisplayStart = Convert.ToInt32(request["iDisplayStart"]); + obj.iDisplayLength = Convert.ToInt32(request["iDisplayLength"]); + obj.iColumns = Convert.ToInt32(request["iColumns"]); + obj.sSearch = request["sSearch"]; + obj.bEscapeRegex = Convert.ToBoolean(request["bEscapeRegex"]); + obj.iSortingCols = Convert.ToInt32(request["iSortingCols"]); + obj.sEcho = int.Parse(request["sEcho"]); + + for (int i = 0; i < obj.iColumns; i++) + { + obj.bSortable.Add(Convert.ToBoolean(request["bSortable_" + i])); + obj.bSearchable.Add(Convert.ToBoolean(request["bSearchable_" + i])); + obj.sSearchColumns.Add(request["sSearch_" + i]); + obj.bEscapeRegexColumns.Add(Convert.ToBoolean(request["bEscapeRegex_" + i])); + obj.iSortCol.Add(Convert.ToInt32(request["iSortCol_" + i])); + obj.sSortDir.Add(request["sSortDir_" + i]); + obj.sName.Add(request["sName_" + i]); + obj.sTitle.Add(request["sTitle_" + i]); + obj.bVisible.Add(Convert.ToBoolean(request["bVisible_" + i])); + } + return obj; + } + } } \ No newline at end of file diff --git a/Mvc.JQuery.Datatables/DataTablesParam.cs b/Mvc.JQuery.Datatables/DataTablesParam.cs index bebc44f..cd5cd41 100644 --- a/Mvc.JQuery.Datatables/DataTablesParam.cs +++ b/Mvc.JQuery.Datatables/DataTablesParam.cs @@ -1,41 +1,47 @@ -using System.Collections.Generic; - -namespace Mvc.JQuery.Datatables -{ - /// - /// Model binder for datatables.js parameters a la http://geeksprogramando.blogspot.com/2011/02/jquery-datatables-plug-in-with-asp-mvc.html - /// - - public class DataTablesParam - { - public int iDisplayStart { get; set; } - public int iDisplayLength { get; set; } - public int iColumns { get; set; } - public string sSearch { get; set; } - public bool bEscapeRegex { get; set; } - public int iSortingCols { get; set; } - public int sEcho { get; set; } - public List bSortable { get; set; } - public List bSearchable { get; set; } - public List sSearchColumns { get; set; } - public List iSortCol { get; set; } - public List sSortDir { get; set; } - public List bEscapeRegexColumns { get; set; } - - public DataTablesParam() - { - bSortable = new List(); - bSearchable = new List(); - sSearchColumns = new List(); - iSortCol = new List(); - sSortDir = new List(); - bEscapeRegexColumns = new List(); - } - } - //public enum DataType - //{ - // tInt, - // tString, - // tnone - //} +using System.Collections.Generic; + +namespace Mvc.JQuery.Datatables +{ + /// + /// Model binder for datatables.js parameters a la http://geeksprogramando.blogspot.com/2011/02/jquery-datatables-plug-in-with-asp-mvc.html + /// + + public class DataTablesParam + { + public int iDisplayStart { get; set; } + public int iDisplayLength { get; set; } + public int iColumns { get; set; } + public string sSearch { get; set; } + public bool bEscapeRegex { get; set; } + public int iSortingCols { get; set; } + public int sEcho { get; set; } + public List bSortable { get; set; } + public List bSearchable { get; set; } + public List sSearchColumns { get; set; } + public List iSortCol { get; set; } + public List sSortDir { get; set; } + public List bEscapeRegexColumns { get; set; } + public List sName { get; set; } + public List sTitle { get; set; } + public List bVisible { get; set; } + + public DataTablesParam() + { + bSortable = new List(); + bSearchable = new List(); + sSearchColumns = new List(); + iSortCol = new List(); + sSortDir = new List(); + bEscapeRegexColumns = new List(); + sName = new List(); + sTitle = new List(); + bVisible = new List(); + } + } + //public enum DataType + //{ + // tInt, + // tString, + // tnone + //} } \ No newline at end of file diff --git a/Mvc.JQuery.Datatables/DataTablesResult.cs b/Mvc.JQuery.Datatables/DataTablesResult.cs index 11b699d..834df81 100644 --- a/Mvc.JQuery.Datatables/DataTablesResult.cs +++ b/Mvc.JQuery.Datatables/DataTablesResult.cs @@ -1,128 +1,128 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using Mvc.JQuery.Datatables.DynamicLinq; - -namespace Mvc.JQuery.Datatables -{ - public class DataTablesResult : JsonResult - { - public static DataTablesResult Create(IQueryable q, DataTablesParam dataTableParam, Func transform) - { - return new DataTablesResult(q, dataTableParam, transform); - } - public static DataTablesResult Create(IQueryable q, DataTablesParam dataTableParam) - { - return new DataTablesResult(q, dataTableParam, t => t); - } - - public static DataTablesResult CreateResultUsingEnumerable(IEnumerable q, DataTablesParam dataTableParam) - { - return new DataTablesResult(q.AsQueryable(), dataTableParam, t => t); - } - - public static DataTablesResult Create(object queryable, DataTablesParam dataTableParam) - { - queryable = ((IEnumerable) queryable).AsQueryable(); - var s = "Create"; - - var openCreateMethod = - typeof (DataTablesResult).GetMethods().Single(x => x.Name == s && x.GetGenericArguments().Count() == 1); - var queryableType = queryable.GetType().GetGenericArguments()[0]; - var closedCreateMethod = openCreateMethod.MakeGenericMethod(queryableType); - return (DataTablesResult) closedCreateMethod.Invoke(null, new[] {queryable, dataTableParam}); - } - - } - public class DataTablesResult : DataTablesResult - { - - } - public class DataTablesResult : DataTablesResult - { - private readonly Func _transform; - - public DataTablesResult(IQueryable q, DataTablesParam dataTableParam, Func transform) - { - - _transform = transform; - var properties = typeof(TRes).GetProperties(); - - var content = GetResults(q, dataTableParam, properties.Select(p => Tuple.Create(p.Name, p.PropertyType)).ToArray()); - this.Data = content; - this.JsonRequestBehavior = JsonRequestBehavior.DenyGet; - } - - static readonly List PropertyTransformers = new List() - { - Guard(dateTimeOffset => dateTimeOffset.ToLocalTime().ToString("g")), - Guard(dateTime => dateTime.ToLocalTime().ToString("g")), - Guard(s => s.ToHtmlString()), - Guard(o => (o ?? "").ToString()) - }; - - public delegate object PropertyTransformer(Type type, object value); - public delegate object GuardedValueTransformer(TVal value); - - static PropertyTransformer Guard(GuardedValueTransformer transformer) - { - return (t, v) => - { - if (!typeof(TVal).IsAssignableFrom(t)) - { - return null; - } - return transformer((TVal) v); - }; - } - public static void RegisterFilter(GuardedValueTransformer filter) - { - PropertyTransformers.Add(Guard(filter)); - } - private DataTablesData GetResults(IQueryable data, DataTablesParam param, Tuple[] searchColumns) - { - - int totalRecords = data.Count(); - - - int totalRecordsDisplay; - - var filters = new DataTablesFilter(); - - - var dataArray = data.Select(_transform).AsQueryable(); - dataArray = filters.FilterPagingSortingSearch(param, dataArray, out totalRecordsDisplay, searchColumns).Cast(); - - var type = typeof(TRes); - var properties = type.GetProperties(); - - var toArrayQuery = from i in dataArray - let pairs = properties.Select(p => new {p.PropertyType, Value = (p.GetGetMethod().Invoke(i, null))}) - let values = pairs.Select(p => GetTransformedValue(p.PropertyType, p.Value)) - select values; - - var result = new DataTablesData - { - iTotalRecords = totalRecords, - iTotalDisplayRecords = totalRecordsDisplay, - sEcho = param.sEcho, - aaData = toArrayQuery.ToArray() - }; - - return result; - } - - private object GetTransformedValue(Type propertyType, object value) - { - foreach (var transformer in PropertyTransformers) - { - var result = transformer(propertyType, value); - if (result != null) return result; - } - return (value as object ?? "").ToString(); - } - } +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using Mvc.JQuery.Datatables.DynamicLinq; + +namespace Mvc.JQuery.Datatables +{ + public class DataTablesResult : JsonResult + { + public static DataTablesResult Create(IQueryable q, DataTablesParam dataTableParam, Func transform) + { + return new DataTablesResult(q, dataTableParam, transform); + } + public static DataTablesResult Create(IQueryable q, DataTablesParam dataTableParam) + { + return new DataTablesResult(q, dataTableParam, t => t); + } + + public static DataTablesResult CreateResultUsingEnumerable(IEnumerable q, DataTablesParam dataTableParam) + { + return new DataTablesResult(q.AsQueryable(), dataTableParam, t => t); + } + + public static DataTablesResult Create(object queryable, DataTablesParam dataTableParam) + { + queryable = ((IEnumerable) queryable).AsQueryable(); + var s = "Create"; + + var openCreateMethod = + typeof (DataTablesResult).GetMethods().Single(x => x.Name == s && x.GetGenericArguments().Count() == 1); + var queryableType = queryable.GetType().GetGenericArguments()[0]; + var closedCreateMethod = openCreateMethod.MakeGenericMethod(queryableType); + return (DataTablesResult) closedCreateMethod.Invoke(null, new[] {queryable, dataTableParam}); + } + + } + public class DataTablesResult : DataTablesResult + { + + } + public class DataTablesResult : DataTablesResult + { + private readonly Func _transform; + + public DataTablesResult(IQueryable q, DataTablesParam dataTableParam, Func transform) + { + + _transform = transform; + + var columns = DataTablesHelper.BuildColumns(); + var content = GetResults(q, dataTableParam, columns); + this.Data = content; + this.JsonRequestBehavior = JsonRequestBehavior.DenyGet; + } + + static readonly List PropertyTransformers = new List() + { + Guard(dateTimeOffset => dateTimeOffset.ToLocalTime().ToString("g")), + Guard(dateTime => dateTime.ToLocalTime().ToString("g")), + Guard(s => s.ToHtmlString()), + Guard(o => (o ?? "").ToString()) + }; + + public delegate object PropertyTransformer(Type type, object value); + public delegate object GuardedValueTransformer(TVal value); + + static PropertyTransformer Guard(GuardedValueTransformer transformer) + { + return (t, v) => + { + if (!typeof(TVal).IsAssignableFrom(t)) + { + return null; + } + return transformer((TVal) v); + }; + } + public static void RegisterFilter(GuardedValueTransformer filter) + { + PropertyTransformers.Add(Guard(filter)); + } + private DataTablesData GetResults(IQueryable data, DataTablesParam param, Tuple[] searchColumns) + { + + int totalRecords = data.Count(); + + + int totalRecordsDisplay; + + var filters = new DataTablesFilter(); + + + var dataArray = data.Select(_transform).AsQueryable(); + dataArray = filters.FilterPagingSortingSearch(param, dataArray, out totalRecordsDisplay, searchColumns).Cast(); + + var type = typeof(TRes); + var properties = type.GetProperties(); + + var toArrayQuery = from i in dataArray + let pairs = properties.Select(p => new {p.PropertyType, Value = (p.GetGetMethod().Invoke(i, null))}) + let values = pairs.Select(p => GetTransformedValue(p.PropertyType, p.Value)) + select values; + + var result = new DataTablesData + { + iTotalRecords = totalRecords, + iTotalDisplayRecords = totalRecordsDisplay, + sEcho = param.sEcho, + aaData = toArrayQuery.ToArray() + }; + + return result; + } + + private object GetTransformedValue(Type propertyType, object value) + { + foreach (var transformer in PropertyTransformers) + { + var result = transformer(propertyType, value); + if (result != null) return result; + } + return (value as object ?? "").ToString(); + } + } } \ No newline at end of file diff --git a/Mvc.JQuery.Datatables/Mvc.JQuery.Datatables.csproj b/Mvc.JQuery.Datatables/Mvc.JQuery.Datatables.csproj index 0f7315b..7c4a30a 100644 --- a/Mvc.JQuery.Datatables/Mvc.JQuery.Datatables.csproj +++ b/Mvc.JQuery.Datatables/Mvc.JQuery.Datatables.csproj @@ -1,137 +1,139 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {389ADE94-7C32-4885-812E-68A2A74C82D8} - Library - Properties - Mvc.JQuery.Datatables - Mvc.JQuery.Datatables - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - True - ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - - - - - - - - - ..\packages\WebActivator.1.5\lib\net40\WebActivator.dll - - - - - - - - - - - - - - - - - Views\Shared\DataTable.cshtml - - - - Designer - - - - - - - - - - - - - - - Scripts\jquery.dataTables.columnFilter.js - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {389ADE94-7C32-4885-812E-68A2A74C82D8} + Library + Properties + Mvc.JQuery.Datatables + Mvc.JQuery.Datatables + v4.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + + + + + + + + + + ..\packages\WebActivator.1.5\lib\net40\WebActivator.dll + + + + + + + + + + + + + + + + + + Views\Shared\DataTable.cshtml + + + + Designer + + + + + + + + + + + + + + + Scripts\jquery.dataTables.columnFilter.js + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file