Я хочу использовать jQuery DataTables в моем проекте ASP.NET MVC 5.
Я действительно использовал datatable и его работу отлично, но проблема в том, что мне пришлось вручную устанавливать фильтр и запросы, и у меня такое чувство, что я пытаюсь реализовать данные в mvc, это не совсем правильно. Да, я получаю результаты, но я хочу следовать и стандарты, и я хочу что-то, что мне не нужно вводить фильтр и код разбивки на страницы снова и снова, я только отправляю параметры какой-либо функции или класса, и я получаю результат.
Вот почему я пытаюсь найти некоторую библиотеку datatables с соответствующей документацией.
Когда я наткнулся на эту библиотеку.
https://github.com/ALMMa/datatables.mvc
но нет хорошей документации, чтобы я мог понять, что на самом деле происходит в этой библиотеке или как использовать эту библиотеку?
Да, я пробовал эту библиотеку, но из-за незнания С# и asp.net я не понимаю, как ее реализовать, и я не могу найти какой-либо пример, связанный с этой библиотекой, на который я мог бы понять работу этой библиотеки.
однако я также наткнулся на этот хороший документированный процесс.
http://www.codeproject.com/Articles/155422/jQuery-DataTables-and-ASP-NET-MVC-Integration-Part
Это отлично работало, поскольку они дали очень хорошее подробное объяснение того, как реализовать.
Я сделал свой код контроллера. Что-то вроде этого.
public ActionResult Index(jQueryDataTableParamModel param = null)
{
if (Request.IsAjaxRequest() && param != null)
{
var allCategories = _db.Categories.ToList();
IEnumerable<Category> categories;
var sortColumnIndex = Convert.ToInt32(Request["iSortCol_0"]);
var sortDirection = Request["sSortDir_0"]; // asc or desc
Func<Category,string> orderingFunction = (c => sortColumnIndex==1? c.Name :
sortColumnIndex==2? c.SortOrder.ToString(): c.Status.ToString());
if (!string.IsNullOrEmpty(param.sSearch))
{
if(sortDirection == "desc"){
categories = (from category in allCategories
where category.Name.ToLower().Contains(param.sSearch.ToLower())
select category).OrderByDescending(orderingFunction).Skip(param.iDisplayStart).Take(param.iDisplayLength);
}
else
{
categories = (from category in allCategories
where category.Name.ToLower().Contains(param.sSearch.ToLower())
select category).OrderBy(orderingFunction).Skip(param.iDisplayStart).Take(param.iDisplayLength);
}
}
else
{
if (sortDirection == "desc") {
categories = (from category in allCategories
select category).OrderByDescending(orderingFunction).Skip(param.iDisplayStart).Take(param.iDisplayLength);
}
else{
categories = (from category in allCategories
select category).OrderBy(orderingFunction).Skip(param.iDisplayStart).Take(param.iDisplayLength);
}
}
var actionButtons = "<div class='btn-group'>"+
"<button class='btn btn-primary btn-gradient btn-sm' type='button'>"+
"<span class='fa fa-pencil'></span>"+
"</button>";
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = categories.Count(),
iTotalDisplayRecords = categories.Count(),
aaData = (from category in categories
select new[] { category.CategoryID.ToString(), category.Name, category.SortOrder.ToString(), actionButtons }).ToArray()
},
JsonRequestBehavior.AllowGet);
}
return View();
}
Но, как вы видите, есть много кода всего за один метод, если есть больше методов для данных, мне придется писать весь код снова и снова. поэтому вместо этого можно сделать какой-то общий класс данных или функцию и вызвать его, предоставив некоторые параметры, и я получу желаемый результат.
У меня нет опыта работы с ASP.NET MVC5 или С#, это было несколько дней, когда я работаю над MVC 5. Поэтому, если есть какие-то лучшие способы достижения результатов, которые я реализовал здесь в своем коде, пожалуйста, поделитесь этим и любым предложением думаю, вы думаете, должно быть хорошо для меня в отношении данных.
Я использую настраиваемое связующее устройство и JsonConverter (для JSON.NET):
Пример модели, содержащей запрос таблицы данных:
public class MyModel
{
[JsonConverter(typeof(DataTableConverter))]
public DataTableRequest DataTableRequest { get; set; }
// other properties
}
то метод действия будет выглядеть так:
[HttpPost]
public virtual ActionResult GetDataTableData(MyModel myModel)
{
}
таблица данных DataTableRequest. GetOrderByExpression возвращает динамическое выражение Linq:
public class DataTableRequest
{
public int PageIndex { get; private set; }
public int PageSize { get; private set; }
public string Search { get; private set; }
private List<SortBy> SortingColumns { get; set; }
public int SEcho { get; private set; }
public DataTableRequest(int pageIndex, int pageSize, string search, List<SortBy> sortingColumns, int sEcho)
{
PageIndex = pageIndex;
PageSize = pageSize;
Search = search;
SortingColumns = sortingColumns;
SEcho = sEcho;
}
public string GetOrderByExpression()
{
// could be passed to EntityFramework with DynamicLinq like query.OrderBy(dataTableRequest.GetOrderByExpression())
var columnDirectionPairs = SortingColumns.Select(c => Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(c.Column.Replace("_", ".")) + " " + c.Direction);
var orderByExpression = string.Join(", ", columnDirectionPairs);
return orderByExpression;
}
public class SortBy
{
public SortBy(string column, string direction)
{
Guard.ArgumentNotNullOrEmpty(column, "column");
Guard.ArgumentNotNullOrEmpty(direction, "direction");
Column = column;
Direction = direction;
}
public string Column { get; set; }
public string Direction { get; set; }
}
}
преобразователь таблицы данных (используется для сериализации в json):
public class DataTableConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DataTableRequest);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jArray = JArray.Load(reader);
var tableValueCollection = jArray.Select(x => new { Name = x["name"].Value<string>(), Value = x["value"].Value<string>() }).ToDictionary(x => x.Name, x => x.Value);
var numberOfColumns = int.Parse(tableValueCollection["iColumns"], CultureInfo.InvariantCulture);
var columns = new List<string>();
for (int i = 0; i < numberOfColumns; i++)
{
var queryParamName = string.Format("mDataProp_{0}", i.ToString(CultureInfo.InvariantCulture));
columns.Add(tableValueCollection[queryParamName]);
}
var numberOfSortingColumns = int.Parse(tableValueCollection["iSortingCols"], CultureInfo.InvariantCulture);
var sortingColumns = new List<DataTableRequest.SortBy>();
for (int i = 0; i < numberOfSortingColumns; i++)
{
var sortColQueryParamName = string.Format("iSortCol_{0}", i.ToString(CultureInfo.InvariantCulture));
if (tableValueCollection[sortColQueryParamName] != null)
{
var sortDirQueryParamName = string.Format("sSortDir_{0}", i.ToString(CultureInfo.InvariantCulture));
var sortingDirection = tableValueCollection[sortDirQueryParamName];
var sortingColumnIndex = int.Parse(tableValueCollection[sortColQueryParamName], CultureInfo.InvariantCulture);
var sortingColumnName = columns[sortingColumnIndex];
sortingColumns.Add(new DataTableRequest.SortBy(sortingColumnName, sortingDirection));
}
}
var displayStart = int.Parse(tableValueCollection["iDisplayStart"], CultureInfo.InvariantCulture);
var displayLength = int.Parse(tableValueCollection["iDisplayLength"], CultureInfo.InvariantCulture);
var pageSize = displayLength;
var pageIndex = displayStart / displayLength;
string search = null;
if (tableValueCollection.ContainsKey("sSearch"))
{
search = tableValueCollection["sSearch"];
}
var sEcho = int.Parse(tableValueCollection["sEcho"], CultureInfo.InvariantCulture);
var dataTableRequest = new DataTableRequest(pageIndex, pageSize, search, sortingColumns, sEcho);
return dataTableRequest;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
DataTableModelBinder используется для десериализации объекта DataTableRequest:
public class DataTableModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
var contentType = request.ContentType;
if (!contentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
return (null);
request.InputStream.Seek(0, SeekOrigin.Begin);
var bodyText = new StreamReader(request.InputStream).ReadToEnd();
if (string.IsNullOrEmpty(bodyText)) return (null);
var jsonObj = JObject.Parse(bodyText);
var jArray = (JArray)jsonObj["aoData"];
var tableValueCollection = jArray.Select(x => new { Name = x["name"].Value<string>(), Value = x["value"].Value<string>() }).ToDictionary(x => x.Name, x => x.Value);
var numberOfColumns = int.Parse(tableValueCollection["iColumns"], CultureInfo.InvariantCulture);
var columns = new List<string>();
for (int i = 0; i < numberOfColumns; i++)
{
var queryParamName = string.Format("mDataProp_{0}", i.ToString(CultureInfo.InvariantCulture));
columns.Add(tableValueCollection[queryParamName]);
}
var numberOfSortingColumns = int.Parse(tableValueCollection["iSortingCols"], CultureInfo.InvariantCulture);
var sortingColumns = new List<DataTableRequest.SortBy>();
for (int i = 0; i < numberOfSortingColumns; i++)
{
var sortColQueryParamName = string.Format("iSortCol_{0}", i.ToString(CultureInfo.InvariantCulture));
if (tableValueCollection[sortColQueryParamName] != null)
{
var sortDirQueryParamName = string.Format("sSortDir_{0}", i.ToString(CultureInfo.InvariantCulture));
var sortingDirection = tableValueCollection[sortDirQueryParamName];
var sortingColumnIndex = int.Parse(tableValueCollection[sortColQueryParamName], CultureInfo.InvariantCulture);
var sortingColumnName = columns[sortingColumnIndex];
sortingColumns.Add(new DataTableRequest.SortBy(sortingColumnName, sortingDirection));
}
}
var displayStart = int.Parse(tableValueCollection["iDisplayStart"], CultureInfo.InvariantCulture);
var displayLength = int.Parse(tableValueCollection["iDisplayLength"], CultureInfo.InvariantCulture);
var pageSize = displayLength;
var pageIndex = displayStart / displayLength;
string search = null;
if (tableValueCollection.ContainsKey("sSearch"))
{
search = tableValueCollection["sSearch"];
}
var sEcho = int.Parse(tableValueCollection["sEcho"], CultureInfo.InvariantCulture);
var dataTableRequest = new DataTableRequest(pageIndex, pageSize, search, sortingColumns, sEcho);
return dataTableRequest;
}
}
зарегистрировать привязку модели на Application_Start в Global.asax.cs:
ModelBinders.Binders.Add(typeof (DataTableRequest), new DataTableModelBinder());
Я использую DataTables 1.9.4 и следующею привязку json model:
public class JsonModelBinder : DefaultModelBinder
{
public static JsonSerializerSettings GlobalSerializerSettings
{
get
{
return new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Converters = { new IsoDateTimeConverter() }
};
}
}
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (!IsJSONRequest(controllerContext))
{
return base.BindModel(controllerContext, bindingContext);
}
// Get the JSON data that been posted
var request = controllerContext.HttpContext.Request;
request.InputStream.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(request.InputStream);
var jsonStringData = streamReader.ReadToEnd();
if (string.IsNullOrEmpty(jsonStringData))
return null;
return JsonConvert.DeserializeObject(jsonStringData, bindingContext.ModelMetadata.ModelType, GlobalSerializerSettings);
}
protected static bool IsJSONRequest(ControllerContext controllerContext)
{
var contentType = controllerContext.HttpContext.Request.ContentType;
return contentType.Contains("application/json");
}
}
заменив связующее устройство по умолчанию:
ModelBinders.Binders.DefaultBinder = new JsonModelBinder();