【问题标题】:Model binding new Datatables 1.10 parameters模型绑定新的 Datatables 1.10 参数
【发布时间】:2014-06-23 11:59:41
【问题描述】:

在 Datatables 1.10 中,ajax 服务器端参数从

public class DataTableParamModel
{ 
    public string sEcho{ get; set; }
    public string sSearch{ get; set; }
    public int iDisplayLength{ get; set; }
    public int iDisplayStart{ get; set; }
    public int iColumns{ get; set; }
    public int iSortingCols{ get; set; }
    public string sColumns{ get; set; }
}

到(API 这里http://datatables.net/manual/server-side

columns[i][data]    
columns[i][name]    
columns[i][orderable]
columns[i][search][regex]
columns[i][search][value]   
columns[i][searchable]  
...     
draw    
length  
order[i][column]    
order[i][dir]
... 
search[regex]
search[value]   
start

有些容易绑定

public class DataTableParamModel
{ 
    public string draw { get; set; }
    public int length{ get; set; }
    public int start { get; set; }
}

但新的数组格式看起来很棘手。

映射新参数格式的合适模型是什么?

【问题讨论】:

    标签: c# asp.net-mvc json datatables jquery-datatables


    【解决方案1】:

    这是一个模型绑定器和将绑定这些新参数的类...

    参数型号:

    [ModelBinder(typeof(DTModelBinder))]
    public class DTParameterModel
    {
        /// <summary>
        /// Draw counter. This is used by DataTables to ensure that the Ajax returns from 
        /// server-side processing requests are drawn in sequence by DataTables 
        /// </summary>
        public int Draw { get; set; }
    
        /// <summary>
        /// Paging first record indicator. This is the start point in the current data set 
        /// (0 index based - i.e. 0 is the first record)
        /// </summary>
        public int Start { get; set; }
    
        /// <summary>
        /// Number of records that the table can display in the current draw. It is expected
        /// that the number of records returned will be equal to this number, unless the 
        /// server has fewer records to return. Note that this can be -1 to indicate that 
        /// all records should be returned (although that negates any benefits of 
        /// server-side processing!)
        /// </summary>
        public int Length { get; set; }
    
        /// <summary>
        /// Global Search for the table
        /// </summary>
        public DTSearch Search { get; set; }
    
        /// <summary>
        /// Collection of all column indexes and their sort directions
        /// </summary>
        public IEnumerable<DTOrder> Order { get; set; }
    
        /// <summary>
        /// Collection of all columns in the table
        /// </summary>
        public IEnumerable<DTColumn> Columns { get; set; }
    }
    
    /// <summary>
    /// Represents search values entered into the table
    /// </summary>
    public sealed class DTSearch
    {
        /// <summary>
        /// Global search value. To be applied to all columns which have searchable as true
        /// </summary>
        public string Value { get; set; }
    
        /// <summary>
        /// true if the global filter should be treated as a regular expression for advanced 
        /// searching, false otherwise. Note that normally server-side processing scripts 
        /// will not perform regular expression searching for performance reasons on large 
        /// data sets, but it is technically possible and at the discretion of your script
        /// </summary>
        public bool Regex { get; set; }
    }
    
    /// <summary>
    /// Represents a column and it's order direction
    /// </summary>
    public sealed class DTOrder
    {
        /// <summary>
        /// Column to which ordering should be applied. This is an index reference to the 
        /// columns array of information that is also submitted to the server
        /// </summary>
        public int Column { get; set; }
    
        /// <summary>
        /// Ordering direction for this column. It will be asc or desc to indicate ascending
        /// ordering or descending ordering, respectively
        /// </summary>
        public string Dir { get; set; }
    }
    
    /// <summary>
    /// Represents an individual column in the table
    /// </summary>
    public sealed class DTColumn
    {
        /// <summary>
        /// Column's data source
        /// </summary>
        public string Data { get; set; }
    
        /// <summary>
        /// Column's name
        /// </summary>
        public string Name { get; set; }
    
        /// <summary>
        /// Flag to indicate if this column is orderable (true) or not (false)
        /// </summary>
        public bool Orderable { get; set; }
    
        /// <summary>
        /// Flag to indicate if this column is searchable (true) or not (false)
        /// </summary>
        public bool Searchable { get; set; }
    
        /// <summary>
        /// Search to apply to this specific column.
        /// </summary>
        public DTSearch Search { get; set; }
    }
    

    模型绑定器:

    /// <summary>
    /// Model Binder for DTParameterModel (DataTables)
    /// </summary>
    public class DTModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            base.BindModel(controllerContext, bindingContext);
            var request = controllerContext.HttpContext.Request;
            // Retrieve request data
            var draw = Convert.ToInt32(request["draw"]);
            var start = Convert.ToInt32(request["start"]);
            var length = Convert.ToInt32(request["length"]);
            // Search
            var search = new DTSearch
            {
                Value = request["search[value]"],
                Regex = Convert.ToBoolean(request["search[regex]"])
            };
            // Order
            var o = 0;
            var order = new List<DTOrder>();
            while (request["order[" + o + "][column]"] != null)
            {
                order.Add(new DTOrder
                {
                    Column = Convert.ToInt32(request["order[" + o + "][column]"]),
                    Dir = request["order[" + o + "][dir]"]
                });
                o++;
            }
            // Columns
            var c = 0;
            var columns = new List<DTColumn>();
            while (request["columns[" + c + "][name]"] != null)
            {
                columns.Add(new DTColumn
                {
                    Data = request["columns[" + c + "][data]"],
                    Name = request["columns[" + c + "][name]"],
                    Orderable = Convert.ToBoolean(request["columns[" + c + "][orderable]"]),
                    Searchable = Convert.ToBoolean(request["columns[" + c + "][searchable]"]),
                    Search = new DTSearch
                    {
                        Value = request["columns[" + c + "][search][value]"],
                        Regex = Convert.ToBoolean(request["columns[" + c + "][search][regex]"])
                    }
                });
                c++;
            }
    
            return new DTParameterModel
            {
                Draw = draw,
                Start = start,
                Length = length,
                Search = search,
                Order = order,
                Columns = columns
            };
        }
    }
    

    用法:

    MyController.cs

    public JsonResult DataTablesList(DTParameterModel model)
    {
        ...
    }
    

    MVC6

    如果您打算使用 MVC6,则不再需要模型绑定器,因为 MVC6 将 JQueryFormValueProvider 包含在可以绑定这些值的默认模型绑定器中。

    不过,模型类本身可能仍然有用。

    有一个bug 将在 2.1.0 中修复,它不允许绑定 HttpGet 但仍然适用于 HttpPost

    【讨论】:

    • 这段代码非常棒,为我节省了大量时间!您还需要在应用程序启动代码中添加一些内容:ModelBinders.Binders.Add(typeof(DTParameterModel), new DTModelBinder());
    • @user2320070 不客气。我还添加了一个使用部分。
    • +1,很棒的代码!我的两分钱,为了更好的可移植性,你可以在不改变 Global.asax.cs 的情况下实现它:在public class DTParameterModel 上方添加[ModelBinder(typeof(DTModelBinder))]。那么,MyController.cs 方法可以只是:public JsonResult DataTablesList(DTParameterModel model)。顺便说一句,您的 DTColumn 类缺少一个属性:public bool Searchable { get; set; } (reference)。
    • 开启上帝模式 +100000
    • 您先生是救生员!一整天都在找这个。谢谢!
    【解决方案2】:

    【讨论】:

    • 它适用于模型活页夹,完全没有问题。现在只是用 EF 实现排序
    【解决方案3】:

    我更改了我的 javascript 以使用旧的 ajax 参数选项,该选项使用旧参数发送到服务器。这是通过$.fn.dataTable.ext.legacy.ajax = true; 完成的,所以现在我的代码变成了...

    $.fn.dataTable.ext.legacy.ajax = true;
    var datatable = $('#data-table').DataTable({
        "processing": true,
        "serverSide": true,
        "ajax": "MyController/AjaxHandlerPaging",
        "pageLength": 25,
        "order": [[2, 'desc']],
        "columns": []
    });
    

    【讨论】:

      【解决方案4】:

      知道这篇文章已经有 2 年历史了,但是对于那些想要将其与 ASP.Net Core MVC 6 一起使用的人。这是@Shoe 提供的转换/升级答案

      模型绑定器:

      using Microsoft.AspNetCore.Mvc.Internal;
      using Microsoft.AspNetCore.Mvc.ModelBinding;
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Threading.Tasks;
      
      namespace TrackingAndTraining.Models
      {
          /// <summary>
          /// Model Binder for DTParameterModel (DataTables)
          /// </summary>
          public class DTModelBinder : IModelBinder
          {
              public Task BindModelAsync(ModelBindingContext bindingContext)
              {
      
                  var request = bindingContext.ActionContext.HttpContext.Request.Form;
                  // Retrieve request data
                  var draw = Convert.ToInt32(request["draw"]);
                  var start = Convert.ToInt32(request["start"]);
                  var length = Convert.ToInt32(request["length"]);
                  // Search
                  var search = new DTSearch
                  {
                      Value = request["search[value]"],
                      Regex = Convert.ToBoolean(request["search[regex]"])
                  };
                  // Order
                  var o = 0;
                  var order = new List<DTOrder>();
                  while (!string.IsNullOrEmpty(request["order[" + o + "][column]"]))
                  {
                      order.Add(new DTOrder
                      {
                          Column = Convert.ToInt32(request["order[" + o + "][column]"]),
                          Dir = request["order[" + o + "][dir]"]
                      });
                      o++;
                  }
                  // Columns
                  var c = 0;
                  var columns = new List<DTColumn>();
                  while (!string.IsNullOrEmpty(request["columns[" + c + "][name]"]))
                  {
                      columns.Add(new DTColumn
                      {
                          Data = request["columns[" + c + "][data]"],
                          Name = request["columns[" + c + "][name]"],
                          Orderable = Convert.ToBoolean(request["columns[" + c + "][orderable]"]),
                          Searchable = Convert.ToBoolean(request["columns[" + c + "][searchable]"]),
                          Search = new DTSearch
                          {
                              Value = request["columns[" + c + "][search][value]"],
                              Regex = Convert.ToBoolean(request["columns[" + c + "][search][regex]"])
                          }
                      });
                      c++;
                  }
      
                  var result = new DTParameterModel
                  {
                      Draw = draw,
                      Start = start,
                      Length = length,
                      Search = search,
                      Order = order,
                      Columns = columns
                  };
      
                  bindingContext.Result = ModelBindingResult.Success(result);
      
                  return TaskCache.CompletedTask;
              }
      
          }
      }
      

      参数型号:

      using Microsoft.AspNetCore.Mvc;
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Threading.Tasks;
      
      namespace TrackingAndTraining.Models
      {
          [ModelBinder(BinderType = typeof(DTModelBinder))]
          public class DTParameterModel
          {
              /// <summary>
              /// Draw counter. This is used by DataTables to ensure that the Ajax returns from 
              /// server-side processing requests are drawn in sequence by DataTables 
              /// </summary>
              public int Draw { get; set; }
      
              /// <summary>
              /// Paging first record indicator. This is the start point in the current data set 
              /// (0 index based - i.e. 0 is the first record)
              /// </summary>
              public int Start { get; set; }
      
              /// <summary>
              /// Number of records that the table can display in the current draw. It is expected
              /// that the number of records returned will be equal to this number, unless the 
              /// server has fewer records to return. Note that this can be -1 to indicate that 
              /// all records should be returned (although that negates any benefits of 
              /// server-side processing!)
              /// </summary>
              public int Length { get; set; }
      
              /// <summary>
              /// Global Search for the table
              /// </summary>
              public DTSearch Search { get; set; }
      
              /// <summary>
              /// Collection of all column indexes and their sort directions
              /// </summary>
              public List<DTOrder> Order { get; set; }
      
              /// <summary>
              /// Collection of all columns in the table
              /// </summary>
              public List<DTColumn> Columns { get; set; }
          }
      
          /// <summary>
          /// Represents search values entered into the table
          /// </summary>
          public sealed class DTSearch
          {
              /// <summary>
              /// Global search value. To be applied to all columns which have searchable as true
              /// </summary>
              public string Value { get; set; }
      
              /// <summary>
              /// true if the global filter should be treated as a regular expression for advanced 
              /// searching, false otherwise. Note that normally server-side processing scripts 
              /// will not perform regular expression searching for performance reasons on large 
              /// data sets, but it is technically possible and at the discretion of your script
              /// </summary>
              public bool Regex { get; set; }
          }
      
          /// <summary>
          /// Represents a column and it's order direction
          /// </summary>
          public sealed class DTOrder
          {
              /// <summary>
              /// Column to which ordering should be applied. This is an index reference to the 
              /// columns array of information that is also submitted to the server
              /// </summary>
              public int Column { get; set; }
      
              /// <summary>
              /// Ordering direction for this column. It will be asc or desc to indicate ascending
              /// ordering or descending ordering, respectively
              /// </summary>
              public string Dir { get; set; }
          }
      
          /// <summary>
          /// Represents an individual column in the table
          /// </summary>
          public sealed class DTColumn
          {
              /// <summary>
              /// Column's data source
              /// </summary>
              public string Data { get; set; }
      
              /// <summary>
              /// Column's name
              /// </summary>
              public string Name { get; set; }
      
              /// <summary>
              /// Flag to indicate if this column is orderable (true) or not (false)
              /// </summary>
              public bool Orderable { get; set; }
      
              /// <summary>
              /// Flag to indicate if this column is searchable (true) or not (false)
              /// </summary>
              public bool Searchable { get; set; }
      
              /// <summary>
              /// Search to apply to this specific column.
              /// </summary>
              public DTSearch Search { get; set; }
          }
      }
      

      再次感谢 @Shoe 的原始帖子。

      【讨论】:

      • 您不需要 MVC6 的模型绑定器,因为它现在包含一个可以转换这些值的提供程序。见here
      • 我已经使用了这个功能,但这不需要你维护发送的字段的名称,作为你的对象中的属性名称吗?并且任何特殊条件都必须放在这些属性的 getter 中。我更喜欢为此使用模型活页夹,可能只是我。
      • mvc6 中的默认模型绑定器将绑定 jquery 格式数据表使用的只是在我为 mvc5 编写的模型绑定器上。您可能仍然会发现数据表模型很有用,但如果您的意图只是绑定数据表,则不再需要像以前那样自定义绑定器。
      【解决方案5】:

      我在迁移到 1.10 时遇到了同样的问题。基本上,我改变了我的参数类(摆脱不支持的参数):

      public class jQueryDataTableParamModel
      {
          /// <summary>
          /// Request sequence number sent by DataTable,
          /// same value must be returned in response
          /// </summary>       
          public string draw { get; set; }
      
          /// <summary>
          /// Number of records that should be shown in table
          /// </summary>
          public int length { get; set; }
      
          /// <summary>
          /// First record that should be shown(used for paging)
          /// </summary>
          public int start { get; set; }
      }
      

      在我的控制器中,我得到搜索值、排序顺序和排序列,如下所示:

              var searchString = Request["search[value]"];
              var sortColumnIndex = Convert.ToInt32(Request["order[0][column]"]);
              var sortDirection = Request["order[0][dir]"]; // asc or desc
      

      【讨论】:

        【解决方案6】:

        可以在here 找到完整的服务器端绑定实现。我遇到了类似的问题,这就是我解决它的方法。

        【讨论】:

          猜你喜欢
          • 2015-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-13
          • 2015-11-10
          • 1970-01-01
          • 2017-04-08
          相关资源
          最近更新 更多