【问题标题】:Library For JQuery DataTables ASP.NET MVC用于 JQuery DataTables ASP.NET MVC 的库
【发布时间】:2014-11-02 12:06:59
【问题描述】:

我想在我的 ASP.NET MVC 5 项目中使用 jQuery DataTables。

我确实使用了数据表并且它工作得非常好,但问题是我必须手动设置过滤器和查询,我感觉我试图在 mvc 中实现数据表的方式不太正确。 是的,我确实得到了结果,但我想遵循和标准,而且我想要一些我不必一次又一次地输入过滤器和分页代码的东西,我只需将参数发送到某个函数或类,我就会得到结果。

这就是为什么我试图寻找一些具有适当文档的数据表库。

当我遇到这个图书馆时。

https://github.com/ALMMa/datatables.mvc

但是没有好的文档可以让我理解该库中真正发生的事情或如何使用该库?

是的,我尝试了那个库,但是由于缺乏 c# 和 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();
        }

但是正如您所见,现在只有 1 种方法中有很多代码,如果数据表有更多方法,我将不得不一次又一次地编写所有代码。所以相反,我是否有可能制作某种常见的数据表类或函数,并通过提供一些参数来调用它,我得到了想要的结果。

我在 ASP.NET MVC5 或 C# 方面没有经验,我已经有几天在 MVC 5 上工作了。所以如果有更好的方法来实现我在代码中实现的结果,请也分享一下关于数据表,您认为对我有好处的任何建议。

【问题讨论】:

  • 我不明白为什么要在后端生成 html 代码,这不是 MVC 的重点。如果您需要一个 html 模板来表示您想要的一些数据,请尝试使用部分视图。
  • @MartinSolev 我可以在控制器类方法中调用局部视图吗??
  • 不,控制器的重点是业务逻辑,而不是客户端逻辑。您可以获取您的数据和所有内容并将其发送到视图,在那里您可以迭代您的类别并将它们中的每一个传递到一个局部视图,该视图可以根据您的需要创建您的 html :)

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


【解决方案1】:

我正在使用自定义模型绑定器和 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 返回Dynamic 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();
    }
}

用于反序列化DataTableRequest对象的DataTableModelBinder:

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;
    }
}

在 Global.asax.cs 中的 Application_Start 上注册模型绑定器:

ModelBinders.Binders.Add(typeof (DataTableRequest), new DataTableModelBinder());

我正在使用 DataTables 1.9.4 和以下 json 模型绑定器:

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's 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();

【讨论】:

  • 嗨,你能和我们分享一个asp.net mvc项目吗?问候
  • @umki 嗨,我不能分享整个项目,但我可以解释一些你感兴趣的部分
  • 你能制作一个与 asp.net mvc jquery 数据表服务器端一起使用的示例项目吗?那会很棒
  • CamelCasePropertyNamesContractResolver 是一个单向进程。 github.com/JamesNK/Newtonsoft.Json/issues/391 不适用于反序列化...
猜你喜欢
  • 2014-07-01
  • 2011-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-04
  • 2017-03-24
  • 1970-01-01
  • 2016-12-12
相关资源
最近更新 更多