Skip to content

Commit 861f2ac

Browse files
committed
Merge pull request mcintyre321#81 from mcshaz/master
Testing for DataTablesParam ModelBinder
2 parents 7ddf439 + 756f442 commit 861f2ac

File tree

9 files changed

+217
-79
lines changed

9 files changed

+217
-79
lines changed

Mvc.JQuery.Datatables/DataTablesModelBinder.cs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,35 @@ public class DataTablesModelBinder : IModelBinder
1010
{
1111
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
1212
{
13-
DataTablesParam obj = new DataTablesParam();
14-
var request = controllerContext.HttpContext.Request.Params;
15-
16-
obj.iDisplayStart = Convert.ToInt32(request["iDisplayStart"]);
17-
obj.iDisplayLength = Convert.ToInt32(request["iDisplayLength"]);
18-
obj.iColumns = Convert.ToInt32(request["iColumns"]);
19-
obj.sSearch = request["sSearch"];
20-
obj.bEscapeRegex = Convert.ToBoolean(request["bEscapeRegex"]);
21-
obj.iSortingCols = Convert.ToInt32(request["iSortingCols"]);
22-
obj.sEcho = int.Parse(request["sEcho"]);
13+
var valueProvider = bindingContext.ValueProvider;
14+
15+
DataTablesParam obj = new DataTablesParam(GetValue<int>(valueProvider, "iColumns"));
16+
17+
obj.iDisplayStart = GetValue<int>(valueProvider, "iDisplayStart");
18+
obj.iDisplayLength = GetValue<int>(valueProvider, "iDisplayLength");
19+
obj.sSearch = GetValue<string>(valueProvider, "sSearch");
20+
obj.bEscapeRegex = GetValue<bool>(valueProvider, "bEscapeRegex");
21+
obj.iSortingCols = GetValue<int>(valueProvider, "iSortingCols");
22+
obj.sEcho = GetValue<int>(valueProvider, "sEcho");
2323

2424
for (int i = 0; i < obj.iColumns; i++)
2525
{
26-
obj.bSortable.Add(Convert.ToBoolean(request["bSortable_" + i]));
27-
obj.bSearchable.Add(Convert.ToBoolean(request["bSearchable_" + i]));
28-
obj.sSearchColumns.Add(request["sSearch_" + i]);
29-
obj.bEscapeRegexColumns.Add(Convert.ToBoolean(request["bEscapeRegex_" + i]));
30-
obj.iSortCol.Add(Convert.ToInt32(request["iSortCol_" + i]));
31-
obj.sSortDir.Add(request["sSortDir_" + i]);
26+
obj.bSortable.Add(GetValue<bool>(valueProvider, "bSortable_" + i));
27+
obj.bSearchable.Add(GetValue<bool>(valueProvider, "bSearchable_" + i));
28+
obj.sSearchColumns.Add(GetValue<string>(valueProvider, "sSearch_" + i));
29+
obj.bEscapeRegexColumns.Add(GetValue<bool>(valueProvider, "bEscapeRegex_" + i));
30+
obj.iSortCol.Add(GetValue<int>(valueProvider, "iSortCol_" + i));
31+
obj.sSortDir.Add(GetValue<string>(valueProvider, "sSortDir_" + i));
3232
}
3333
return obj;
3434
}
35+
36+
private static T GetValue<T>(IValueProvider valueProvider, string key)
37+
{
38+
ValueProviderResult valueResult = valueProvider.GetValue(key);
39+
return (valueResult==null)
40+
? default(T)
41+
: (T)valueResult.ConvertTo(typeof(T));
42+
}
3543
}
3644
}

Mvc.JQuery.Datatables/DataTablesParam.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ public DataTablesParam()
3131
sSortDir = new List<string>();
3232
bEscapeRegexColumns = new List<bool>();
3333
}
34+
35+
public DataTablesParam(int iColumns)
36+
{
37+
this.iColumns = iColumns;
38+
bSortable = new List<bool>(iColumns);
39+
bSearchable = new List<bool>(iColumns);
40+
sSearchColumns = new List<string>(iColumns);
41+
iSortCol = new List<int>(iColumns);
42+
sSortDir = new List<string>(iColumns);
43+
bEscapeRegexColumns = new List<bool>(iColumns);
44+
}
3445
}
3546
//public enum DataType
3647
//{
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
22
using System.ComponentModel.DataAnnotations;
33

4-
namespace Mvc.JQuery.DataTables.Tests
4+
namespace Mvc.JQuery.Datatables.Tests
55
{
66
public class SomeModel
77
{
@@ -10,7 +10,7 @@ public class SomeModel
1010
public string DisplayName { get; set; }
1111
public int Category { get; set; }
1212
public double Scale { get; set; }
13-
13+
public DateTime When { get; set; }
1414
public bool Discounted { get; set; }
1515
}
1616
}

Mvc.Jquery.DataTables.Tests/DummyPocos/SomeView.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.

Mvc.Jquery.DataTables.Tests/Tests.cs renamed to Mvc.Jquery.DataTables.Tests/FilterTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using Mvc.JQuery.Datatables;
66
using NUnit.Framework;
77

8-
namespace Mvc.JQuery.DataTables.Tests
8+
namespace Mvc.JQuery.Datatables.Tests
99
{
1010
public class FilterTests
1111
{

Mvc.Jquery.DataTables.Tests/Fixtures/EntityFramework.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using System.Linq;
77
using Mvc.JQuery.Datatables;
88

9-
namespace Mvc.JQuery.DataTables.Tests
9+
namespace Mvc.JQuery.Datatables.Tests
1010
{
1111
public class EntityFramework : Linq, IDisposable
1212
{

Mvc.Jquery.DataTables.Tests/Fixtures/Linq.cs

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,20 @@
44
using System.Collections;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using System.Reflection;
78

8-
namespace Mvc.JQuery.DataTables.Tests
9+
namespace Mvc.JQuery.Datatables.Tests
910
{
1011
[TestFixture]
1112
public class Linq
1213
{
13-
internal const int SomeModelPropertyCount = 4;
14-
internal const int SomeViewPropertyCount = 4;
1514
private const int TotalRecords = 100;
16-
internal const int DisplayLength = 5;
1715

1816
protected IQueryable<SomeModel> SomeModelQueryable { get; set; }
1917

2018
public Linq()
2119
{
20+
DateTime startDate = new DateTime(2000, 1, 1);
2221
var dataSet = new List<SomeModel>(TotalRecords);
2322
for (var i = 1; i < TotalRecords; i++)
2423
{
@@ -27,7 +26,8 @@ public Linq()
2726
Id = i,
2827
DisplayName = "Name " + i,
2928
Category = i % 4,
30-
Scale = Math.Abs(50 - i)
29+
Scale = Math.Abs(50 - i),
30+
When = startDate.AddDays(i)
3131
});
3232
}
3333
SomeModelQueryable = dataSet.AsQueryable();
@@ -38,40 +38,53 @@ public virtual int[] ExecuteParams(DataTablesParam dataTablesParam)
3838
{
3939
var result = new DataTablesResult<SomeModel>(SomeModelQueryable, dataTablesParam);
4040
var data = result.Data;
41-
return data.RecordIds();
41+
return data.aaData.Select(row => ((SomeModel)row).Id).ToArray();
4242
}
4343

4444
[Test, TestCaseSource(typeof(MyFactoryClass), "TestCases")]
4545
public virtual int[] ExecuteParamsAndTransform(DataTablesParam dataTablesParam)
4646
{
47-
var result = new DataTablesResult<SomeModel>(SomeModelQueryable,
48-
dataTablesParam);
47+
var result = DataTablesResult.Create(SomeModelQueryable,
48+
dataTablesParam,
49+
m => new {
50+
FriendlyWhen = m.When.ToShortDateString(),
51+
});
4952
var data = result.Data;
50-
return data.RecordIds();
53+
return data.aaData.Select(d=>Convert.ToInt32(((IList)d)[0])).ToArray();
5154
}
55+
5256
}
5357
public static class MyFactoryClass
5458
{
59+
static int PropertyCount(Type T)
60+
{
61+
return T.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
62+
.Count(pi=>pi.CanRead);
63+
}
64+
65+
static int DefaultTestCasesLength = 5;
66+
5567
public static IEnumerable TestCases
5668
{
5769
get
5870
{
59-
var dataTablesParam = EmptyParam();
71+
int propertyCount = PropertyCount(typeof(DataTablesParam));
72+
var dataTablesParam = GetEmptyParam(propertyCount);
6073
dataTablesParam.sSortDir[0] = "asc";
6174
dataTablesParam.iSortingCols = 1;
6275
yield return new TestCaseData(dataTablesParam)
63-
.Returns(Enumerable.Range(1, Linq.DisplayLength).ToArray())
76+
.Returns(Enumerable.Range(1, DefaultTestCasesLength).ToArray())
6477
.SetName("SimpleOrder")
6578
.SetDescription("Simple Ordering");
6679

67-
dataTablesParam = EmptyParam();
80+
dataTablesParam = GetEmptyParam(propertyCount);
6881
dataTablesParam.sSearch = "Name 10";
6982
yield return new TestCaseData(dataTablesParam)
7083
.Returns(new int[] { 10 })
7184
.SetName("SingleRecordSearch")
7285
.SetDescription("Single Record Text Search");
7386

74-
dataTablesParam = EmptyParam();
87+
dataTablesParam = GetEmptyParam(propertyCount);
7588
dataTablesParam.iSortingCols = 1;
7689
dataTablesParam.iSortCol[0] = 2;
7790
dataTablesParam.sSearchColumns[3] = "25~35";
@@ -83,43 +96,22 @@ public static IEnumerable TestCases
8396
}
8497
}
8598

86-
public static DataTablesParam EmptyParam(int columns = Linq.SomeModelPropertyCount)
99+
static DataTablesParam GetEmptyParam(int columns)
87100
{
88-
return new DataTablesParam
89-
{
90-
bEscapeRegex = false,
91-
bEscapeRegexColumns = LinqTestStaticMethods.Populate<bool>(false, columns),
92-
bSearchable = LinqTestStaticMethods.Populate<bool>(true, columns),
93-
bSortable = LinqTestStaticMethods.Populate<bool>(true, columns),
94-
iColumns = columns,
95-
iDisplayLength = Linq.DisplayLength,
96-
iSortingCols = 1,
97-
iSortCol = LinqTestStaticMethods.Populate<int>(0, columns),
98-
sEcho = 1,
99-
sSearchColumns = LinqTestStaticMethods.Populate<string>("", columns),
100-
sSortDir = LinqTestStaticMethods.Populate<string>(null, columns),
101-
sSearch = ""
102-
};
103-
}
104-
}
101+
var returnVar = new DataTablesParam(columns);
102+
returnVar.iDisplayLength = DefaultTestCasesLength;
103+
returnVar.iSortingCols = 1;
104+
returnVar.sEcho = 1;
105+
returnVar.sSearch = "";
106+
returnVar.bEscapeRegexColumns.AddRange(Enumerable.Repeat(false, columns));
107+
returnVar.bSearchable.AddRange(Enumerable.Repeat(true, columns));
108+
returnVar.bSortable.AddRange(Enumerable.Repeat(true, columns));
109+
returnVar.iSortCol.AddRange(Enumerable.Repeat(0, columns));
110+
returnVar.sSearchColumns.AddRange(Enumerable.Repeat("", columns));
111+
returnVar.sSortDir.AddRange(Enumerable.Repeat<string>(null, columns));
105112

106-
public static class LinqTestStaticMethods
107-
{
108-
public static int[] RecordIds(this DataTablesData data)
109-
{
110-
return data.aaData.Select(row => ((SomeModel) row).Id).ToArray();
111-
}
112-
public static List<Tlist> Populate<Tlist>(Tlist value, int capacity = Linq.SomeModelPropertyCount)
113-
{
114-
var returnVal = new Tlist[capacity];
115-
if (!EqualityComparer<Tlist>.Default.Equals(value, default(Tlist)))
116-
{
117-
for (var i = 0; i < capacity; ++i)
118-
{
119-
returnVal[i] = value;
120-
}
121-
}
122-
return new List<Tlist>(returnVal);
113+
return returnVar;
123114
}
124115
}
116+
125117
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using Mvc.JQuery.Datatables;
2+
using NUnit.Framework;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Collections.Specialized;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Web.Mvc;
9+
using Mvc.JQuery.Datatables.Tests.TestingUtilities;
10+
11+
namespace Mvc.JQuery.Datatables.Tests
12+
{
13+
[TestFixture]
14+
public class ModelBinding
15+
{
16+
[Test]
17+
public void TestDataTablesIModelBinder()
18+
{
19+
Mvc.JQuery.Datatables.Example.RegisterDatatablesModelBinder.Start();
20+
IModelBinder dataTablesBinder = ModelBinders.Binders.GetBinder(typeof(DataTablesParam), false);
21+
Assert.That(dataTablesBinder, Is.Not.Null, "DataTablesParam model binder not found in ModelBindersDictionary");
22+
23+
var formCollection = new NameValueCollection
24+
{
25+
{ "sEcho", "1" },
26+
{ "iColumns", "9" },
27+
{ "sColumns", "" },
28+
{ "iDisplayStart", "0" },
29+
{ "iDisplayLength", "10" },
30+
{ "mDataProp_0", "0" },
31+
{ "mDataProp_1", "1" },
32+
{ "mDataProp_2", "2" },
33+
{ "mDataProp_3", "3" },
34+
{ "mDataProp_4", "4" },
35+
{ "mDataProp_5", "5" },
36+
{ "mDataProp_6", "6" },
37+
{ "mDataProp_7", "7" },
38+
{ "mDataProp_8", "8" },
39+
{ "sSearch", "" },
40+
{ "bRegex", "false" },
41+
{ "sSearch_0", "" },
42+
{ "sSearch_1", "" },
43+
{ "sSearch_2", "" },
44+
{ "sSearch_3", "" },
45+
{ "sSearch_4", "" },
46+
{ "sSearch_5", "" },
47+
{ "sSearch_6", "" },
48+
{ "sSearch_7", "" },
49+
{ "sSearch_8", "" },
50+
{ "bRegex_0", "false" },
51+
{ "bRegex_1", "false" },
52+
{ "bRegex_2", "false" },
53+
{ "bRegex_3", "false" },
54+
{ "bRegex_4", "false" },
55+
{ "bRegex_5", "false" },
56+
{ "bRegex_6", "false" },
57+
{ "bRegex_7", "false" },
58+
{ "bRegex_8", "false" },
59+
{ "bSearchable_0", "true" },
60+
{ "bSearchable_1", "true" },
61+
{ "bSearchable_2", "false" },
62+
{ "bSearchable_3", "true" },
63+
{ "bSearchable_4", "true" },
64+
{ "bSearchable_5", "true" },
65+
{ "bSearchable_6", "true" },
66+
{ "bSearchable_7", "true" },
67+
{ "bSearchable_8", "true" },
68+
{ "iSortCol_0", "0" },
69+
{ "sSortDir_0", "asc" },
70+
{ "iSortingCols", "1" },
71+
{ "bSortable_0", "true" },
72+
{ "bSortable_1", "true" },
73+
{ "bSortable_2", "true" },
74+
{ "bSortable_3", "false" },
75+
{ "bSortable_4", "true" },
76+
{ "bSortable_5", "true" },
77+
{ "bSortable_6", "true" },
78+
{ "bSortable_7", "true" },
79+
{ "bSortable_8", "true" }
80+
};
81+
82+
var res = SetupAndBind<DataTablesParam>(formCollection, dataTablesBinder);
83+
Assert.That(res.iColumns, Is.EqualTo(9), "iColumns");
84+
Assert.That(res.bEscapeRegex, Is.EqualTo(false),"bEscapeRegex");
85+
Assert.That(res.bEscapeRegexColumns, Is.EqualTo(Enumerable.Repeat(false, 9)), "bEscapeRegexColumns");
86+
Assert.That(res.bSearchable, Is.EqualTo(Enumerable.Repeat(true, 9).ReplaceAtIndex(false, 2)), "bSearchable");
87+
Assert.That(res.bSortable, Is.EqualTo(Enumerable.Repeat(true, 9).ReplaceAtIndex(false, 3)), "bSortable");
88+
Assert.That(res.iDisplayLength, Is.EqualTo(10), "iDisplayLength");
89+
Assert.That(res.iDisplayStart, Is.EqualTo(0), "iDisplayStart");
90+
Assert.That(res.iSortCol, Is.EqualTo(Enumerable.Repeat(0, 9)), "iSortCol");
91+
Assert.That(res.iSortingCols, Is.EqualTo(1), "iSortingCols");
92+
Assert.That(res.sEcho, Is.EqualTo(1), "sEcho");
93+
Assert.That(res.sSearch,Is.EqualTo(""),"sSearch");
94+
Assert.That(res.sSearchColumns, Is.EqualTo(Enumerable.Repeat("", 9)), "sSearchColumns");
95+
Assert.That(res.sSortDir, Is.EqualTo(Enumerable.Repeat<string>(null, 9).ReplaceAtIndex("asc", 0)), "sSortDir");
96+
Assert.That(res.bEscapeRegex, Is.EqualTo(false), "bEscapeRegex");
97+
}
98+
99+
//http://www.jamie-dixon.co.uk/unit-testing/unit-testing-your-custom-model-binder/
100+
static TModel SetupAndBind<TModel>(NameValueCollection nameValueCollection, IModelBinder modelBinder)
101+
where TModel : class
102+
{
103+
var valueProvider = new NameValueCollectionValueProvider(nameValueCollection, null);
104+
var modelMetaData = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(TModel));
105+
var controllerContext = new ControllerContext();
106+
var bindingContext = new ModelBindingContext
107+
{
108+
ModelName = string.Empty,
109+
ValueProvider = valueProvider,
110+
ModelMetadata = modelMetaData,
111+
};
112+
113+
return (TModel)modelBinder.BindModel(controllerContext, bindingContext);
114+
}
115+
}
116+
}

0 commit comments

Comments
 (0)