Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions Mvc.JQuery.Datatables/DataTablesModelBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,35 @@ 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"]);
var valueProvider = bindingContext.ValueProvider;

DataTablesParam obj = new DataTablesParam(GetValue<int>(valueProvider, "iColumns"));

obj.iDisplayStart = GetValue<int>(valueProvider, "iDisplayStart");
obj.iDisplayLength = GetValue<int>(valueProvider, "iDisplayLength");
obj.sSearch = GetValue<string>(valueProvider, "sSearch");
obj.bEscapeRegex = GetValue<bool>(valueProvider, "bEscapeRegex");
obj.iSortingCols = GetValue<int>(valueProvider, "iSortingCols");
obj.sEcho = GetValue<int>(valueProvider, "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.bSortable.Add(GetValue<bool>(valueProvider, "bSortable_" + i));
obj.bSearchable.Add(GetValue<bool>(valueProvider, "bSearchable_" + i));
obj.sSearchColumns.Add(GetValue<string>(valueProvider, "sSearch_" + i));
obj.bEscapeRegexColumns.Add(GetValue<bool>(valueProvider, "bEscapeRegex_" + i));
obj.iSortCol.Add(GetValue<int>(valueProvider, "iSortCol_" + i));
obj.sSortDir.Add(GetValue<string>(valueProvider, "sSortDir_" + i));
}
return obj;
}

private static T GetValue<T>(IValueProvider valueProvider, string key)
{
ValueProviderResult valueResult = valueProvider.GetValue(key);
return (valueResult==null)
? default(T)
: (T)valueResult.ConvertTo(typeof(T));
}
}
}
11 changes: 11 additions & 0 deletions Mvc.JQuery.Datatables/DataTablesParam.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ public DataTablesParam()
sSortDir = new List<string>();
bEscapeRegexColumns = new List<bool>();
}

public DataTablesParam(int iColumns)
{
this.iColumns = iColumns;
bSortable = new List<bool>(iColumns);
bSearchable = new List<bool>(iColumns);
sSearchColumns = new List<string>(iColumns);
iSortCol = new List<int>(iColumns);
sSortDir = new List<string>(iColumns);
bEscapeRegexColumns = new List<bool>(iColumns);
}
}
//public enum DataType
//{
Expand Down
4 changes: 2 additions & 2 deletions Mvc.Jquery.DataTables.Tests/DummyPocos/SomeModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.ComponentModel.DataAnnotations;

namespace Mvc.JQuery.DataTables.Tests
namespace Mvc.JQuery.Datatables.Tests
{
public class SomeModel
{
Expand All @@ -10,7 +10,7 @@ public class SomeModel
public string DisplayName { get; set; }
public int Category { get; set; }
public double Scale { get; set; }

public DateTime When { get; set; }
public bool Discounted { get; set; }
}
}
11 changes: 0 additions & 11 deletions Mvc.Jquery.DataTables.Tests/DummyPocos/SomeView.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using Mvc.JQuery.Datatables;
using NUnit.Framework;

namespace Mvc.JQuery.DataTables.Tests
namespace Mvc.JQuery.Datatables.Tests
{
public class FilterTests
{
Expand Down
2 changes: 1 addition & 1 deletion Mvc.Jquery.DataTables.Tests/Fixtures/EntityFramework.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Linq;
using Mvc.JQuery.Datatables;

namespace Mvc.JQuery.DataTables.Tests
namespace Mvc.JQuery.Datatables.Tests
{
public class EntityFramework : Linq, IDisposable
{
Expand Down
88 changes: 40 additions & 48 deletions Mvc.Jquery.DataTables.Tests/Fixtures/Linq.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Mvc.JQuery.DataTables.Tests
namespace Mvc.JQuery.Datatables.Tests
{
[TestFixture]
public class Linq
{
internal const int SomeModelPropertyCount = 4;
internal const int SomeViewPropertyCount = 4;
private const int TotalRecords = 100;
internal const int DisplayLength = 5;

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

public Linq()
{
DateTime startDate = new DateTime(2000, 1, 1);
var dataSet = new List<SomeModel>(TotalRecords);
for (var i = 1; i < TotalRecords; i++)
{
Expand All @@ -27,7 +26,8 @@ public Linq()
Id = i,
DisplayName = "Name " + i,
Category = i % 4,
Scale = Math.Abs(50 - i)
Scale = Math.Abs(50 - i),
When = startDate.AddDays(i)
});
}
SomeModelQueryable = dataSet.AsQueryable();
Expand All @@ -38,40 +38,53 @@ public virtual int[] ExecuteParams(DataTablesParam dataTablesParam)
{
var result = new DataTablesResult<SomeModel>(SomeModelQueryable, dataTablesParam);
var data = result.Data;
return data.RecordIds();
return data.aaData.Select(row => ((SomeModel)row).Id).ToArray();
}

[Test, TestCaseSource(typeof(MyFactoryClass), "TestCases")]
public virtual int[] ExecuteParamsAndTransform(DataTablesParam dataTablesParam)
{
var result = new DataTablesResult<SomeModel>(SomeModelQueryable,
dataTablesParam);
var result = DataTablesResult.Create(SomeModelQueryable,
dataTablesParam,
m => new {
FriendlyWhen = m.When.ToShortDateString(),
});
var data = result.Data;
return data.RecordIds();
return data.aaData.Select(d=>Convert.ToInt32(((IList)d)[0])).ToArray();
}

}
public static class MyFactoryClass
{
static int PropertyCount(Type T)
{
return T.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Count(pi=>pi.CanRead);
}

static int DefaultTestCasesLength = 5;

public static IEnumerable TestCases
{
get
{
var dataTablesParam = EmptyParam();
int propertyCount = PropertyCount(typeof(DataTablesParam));
var dataTablesParam = GetEmptyParam(propertyCount);
dataTablesParam.sSortDir[0] = "asc";
dataTablesParam.iSortingCols = 1;
yield return new TestCaseData(dataTablesParam)
.Returns(Enumerable.Range(1, Linq.DisplayLength).ToArray())
.Returns(Enumerable.Range(1, DefaultTestCasesLength).ToArray())
.SetName("SimpleOrder")
.SetDescription("Simple Ordering");

dataTablesParam = EmptyParam();
dataTablesParam = GetEmptyParam(propertyCount);
dataTablesParam.sSearch = "Name 10";
yield return new TestCaseData(dataTablesParam)
.Returns(new int[] { 10 })
.SetName("SingleRecordSearch")
.SetDescription("Single Record Text Search");

dataTablesParam = EmptyParam();
dataTablesParam = GetEmptyParam(propertyCount);
dataTablesParam.iSortingCols = 1;
dataTablesParam.iSortCol[0] = 2;
dataTablesParam.sSearchColumns[3] = "25~35";
Expand All @@ -83,43 +96,22 @@ public static IEnumerable TestCases
}
}

public static DataTablesParam EmptyParam(int columns = Linq.SomeModelPropertyCount)
static DataTablesParam GetEmptyParam(int columns)
{
return new DataTablesParam
{
bEscapeRegex = false,
bEscapeRegexColumns = LinqTestStaticMethods.Populate<bool>(false, columns),
bSearchable = LinqTestStaticMethods.Populate<bool>(true, columns),
bSortable = LinqTestStaticMethods.Populate<bool>(true, columns),
iColumns = columns,
iDisplayLength = Linq.DisplayLength,
iSortingCols = 1,
iSortCol = LinqTestStaticMethods.Populate<int>(0, columns),
sEcho = 1,
sSearchColumns = LinqTestStaticMethods.Populate<string>("", columns),
sSortDir = LinqTestStaticMethods.Populate<string>(null, columns),
sSearch = ""
};
}
}
var returnVar = new DataTablesParam(columns);
returnVar.iDisplayLength = DefaultTestCasesLength;
returnVar.iSortingCols = 1;
returnVar.sEcho = 1;
returnVar.sSearch = "";
returnVar.bEscapeRegexColumns.AddRange(Enumerable.Repeat(false, columns));
returnVar.bSearchable.AddRange(Enumerable.Repeat(true, columns));
returnVar.bSortable.AddRange(Enumerable.Repeat(true, columns));
returnVar.iSortCol.AddRange(Enumerable.Repeat(0, columns));
returnVar.sSearchColumns.AddRange(Enumerable.Repeat("", columns));
returnVar.sSortDir.AddRange(Enumerable.Repeat<string>(null, columns));

public static class LinqTestStaticMethods
{
public static int[] RecordIds(this DataTablesData data)
{
return data.aaData.Select(row => ((SomeModel) row).Id).ToArray();
}
public static List<Tlist> Populate<Tlist>(Tlist value, int capacity = Linq.SomeModelPropertyCount)
{
var returnVal = new Tlist[capacity];
if (!EqualityComparer<Tlist>.Default.Equals(value, default(Tlist)))
{
for (var i = 0; i < capacity; ++i)
{
returnVal[i] = value;
}
}
return new List<Tlist>(returnVal);
return returnVar;
}
}

}
116 changes: 116 additions & 0 deletions Mvc.Jquery.DataTables.Tests/Fixtures/ModelBinding.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using Mvc.JQuery.Datatables;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Mvc.JQuery.Datatables.Tests.TestingUtilities;

namespace Mvc.JQuery.Datatables.Tests
{
[TestFixture]
public class ModelBinding
{
[Test]
public void TestDataTablesIModelBinder()
{
Mvc.JQuery.Datatables.Example.RegisterDatatablesModelBinder.Start();
IModelBinder dataTablesBinder = ModelBinders.Binders.GetBinder(typeof(DataTablesParam), false);
Assert.That(dataTablesBinder, Is.Not.Null, "DataTablesParam model binder not found in ModelBindersDictionary");

var formCollection = new NameValueCollection
{
{ "sEcho", "1" },
{ "iColumns", "9" },
{ "sColumns", "" },
{ "iDisplayStart", "0" },
{ "iDisplayLength", "10" },
{ "mDataProp_0", "0" },
{ "mDataProp_1", "1" },
{ "mDataProp_2", "2" },
{ "mDataProp_3", "3" },
{ "mDataProp_4", "4" },
{ "mDataProp_5", "5" },
{ "mDataProp_6", "6" },
{ "mDataProp_7", "7" },
{ "mDataProp_8", "8" },
{ "sSearch", "" },
{ "bRegex", "false" },
{ "sSearch_0", "" },
{ "sSearch_1", "" },
{ "sSearch_2", "" },
{ "sSearch_3", "" },
{ "sSearch_4", "" },
{ "sSearch_5", "" },
{ "sSearch_6", "" },
{ "sSearch_7", "" },
{ "sSearch_8", "" },
{ "bRegex_0", "false" },
{ "bRegex_1", "false" },
{ "bRegex_2", "false" },
{ "bRegex_3", "false" },
{ "bRegex_4", "false" },
{ "bRegex_5", "false" },
{ "bRegex_6", "false" },
{ "bRegex_7", "false" },
{ "bRegex_8", "false" },
{ "bSearchable_0", "true" },
{ "bSearchable_1", "true" },
{ "bSearchable_2", "false" },
{ "bSearchable_3", "true" },
{ "bSearchable_4", "true" },
{ "bSearchable_5", "true" },
{ "bSearchable_6", "true" },
{ "bSearchable_7", "true" },
{ "bSearchable_8", "true" },
{ "iSortCol_0", "0" },
{ "sSortDir_0", "asc" },
{ "iSortingCols", "1" },
{ "bSortable_0", "true" },
{ "bSortable_1", "true" },
{ "bSortable_2", "true" },
{ "bSortable_3", "false" },
{ "bSortable_4", "true" },
{ "bSortable_5", "true" },
{ "bSortable_6", "true" },
{ "bSortable_7", "true" },
{ "bSortable_8", "true" }
};

var res = SetupAndBind<DataTablesParam>(formCollection, dataTablesBinder);
Assert.That(res.iColumns, Is.EqualTo(9), "iColumns");
Assert.That(res.bEscapeRegex, Is.EqualTo(false),"bEscapeRegex");
Assert.That(res.bEscapeRegexColumns, Is.EqualTo(Enumerable.Repeat(false, 9)), "bEscapeRegexColumns");
Assert.That(res.bSearchable, Is.EqualTo(Enumerable.Repeat(true, 9).ReplaceAtIndex(false, 2)), "bSearchable");
Assert.That(res.bSortable, Is.EqualTo(Enumerable.Repeat(true, 9).ReplaceAtIndex(false, 3)), "bSortable");
Assert.That(res.iDisplayLength, Is.EqualTo(10), "iDisplayLength");
Assert.That(res.iDisplayStart, Is.EqualTo(0), "iDisplayStart");
Assert.That(res.iSortCol, Is.EqualTo(Enumerable.Repeat(0, 9)), "iSortCol");
Assert.That(res.iSortingCols, Is.EqualTo(1), "iSortingCols");
Assert.That(res.sEcho, Is.EqualTo(1), "sEcho");
Assert.That(res.sSearch,Is.EqualTo(""),"sSearch");
Assert.That(res.sSearchColumns, Is.EqualTo(Enumerable.Repeat("", 9)), "sSearchColumns");
Assert.That(res.sSortDir, Is.EqualTo(Enumerable.Repeat<string>(null, 9).ReplaceAtIndex("asc", 0)), "sSortDir");
Assert.That(res.bEscapeRegex, Is.EqualTo(false), "bEscapeRegex");
}

//http://www.jamie-dixon.co.uk/unit-testing/unit-testing-your-custom-model-binder/
static TModel SetupAndBind<TModel>(NameValueCollection nameValueCollection, IModelBinder modelBinder)
where TModel : class
{
var valueProvider = new NameValueCollectionValueProvider(nameValueCollection, null);
var modelMetaData = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(TModel));
var controllerContext = new ControllerContext();
var bindingContext = new ModelBindingContext
{
ModelName = string.Empty,
ValueProvider = valueProvider,
ModelMetadata = modelMetaData,
};

return (TModel)modelBinder.BindModel(controllerContext, bindingContext);
}
}
}
Loading