ASP.Net MVC 3 JQGrid

7
阅读了JQGrid控件后,我决定在我的ASP.Net MVC 3 Web应用程序中使用它。首先,我按照Phil Haack的教程http://haacked.com/archive/2009/04/14/using-jquery-grid-with-asp.net-mvc.aspx进行了操作,一切都很好。然后,我尝试将类似的东西实现到我的应用程序中,唯一的区别是我使用的是Linq To Entities。我的View页面已经导入了所有的css和Jquery类,然后我有我的JavaScript函数和包含数据的表格。
<script type="text/javascript">
jQuery(document).ready(function () {
    jQuery("#list").jqGrid({
        url: '/Home/LinqGridData/',
        datatype: 'json',
        mtype: 'GET',
        colNames: ['equipmentID', 'categoryTitle', 'title'],
        colModel: [
      { name: 'equipmentID', index: 'equipmentID', width: 40, align: 'left' },
      { name: 'categoryTitle', index: 'categoryTitle', width: 40, align: 'left' },
      { name: 'title', index: 'title', width: 200, align: 'left'}],
        pager: jQuery('#pager'),
        width: 660,
        height: 'auto',
        rowNum: 10,
        rowList: [5, 10, 20, 50],
        sortname: 'Id',
        sortorder: "desc",
        viewrecords: true,
        imgpath: '/scripts/themes/coffee/images',
        caption: 'My first grid'
    });
}); 

<h2>My Grid Data</h2>
<table id="list" class="scroll" cellpadding="0" cellspacing="0"></table>
<div id="pager" class="scroll" style="text-align:center;"></div>

然后在我的控制器中,我有以下方法,该方法应该返回Json数据

public ActionResult LinqGridData(string sidx, string sord, int page, int rows)
    {
        AssetEntities context = new AssetEntities();

        var query = from e in context.Equipments
                    select e;

        var count = query.Count();

        var result = new
        {
            total = 1,
            page = page,
            records = count,
            rows = (from e in query
                    select new
                    {
                        id = e.equipmentID,
                        cell = new string[]
                        {
                        e.equipmentID.ToString(),
                        e.Category.categoryTitle,
                        e.Department.title
                        }

                    }).ToArray()
        };

        return Json(result, JsonRequestBehavior.AllowGet);

    }

当我运行这段代码时,出现以下错误。
LINQ to Entities does not recognize the method 'System.String ToString()' method

有人知道如何修复这个错误吗?另外,我这样做是正确的方式吗?还是应该从Phil Haack的解释中选择不同的方法,因为他使用Linq to SQL?

非常感谢您的任何反馈。

谢谢大家。


代码的哪一行产生了错误?根据我的猜测,看起来是在你的控制器中发生的(我只看到 .ToString() 方法出现在那里)。 - guildsbounty
是的,你说得对。应用程序在 e.equipment.ToString() 处崩溃了。有什么解决方案吗?谢谢。 - tcode
e.equipmentID的数据类型是什么?如果它已经是一个字符串,那可能就是你的问题。或者,如果它是一些没有内置.toString()功能的自定义数据类型,那也可能是你的问题。 - guildsbounty
e.equipmentID 是 int 类型,需要转换为 string 类型,所以我尝试使用 .ToString()。 - tcode
4个回答

14

EF不支持ToString方法,你必须在没有ToString的情况下检索数据并进行格式化。

这应该可以工作。

public ActionResult LinqGridData(string sidx, string sord, int page, int rows)
{
    AssetEntities context = new AssetEntities();

    var query = from e in context.Equipments
                select e;

    var count = query.Count();

    var result = new
    {
        total = 1,
        page = page,
        records = count,
        rows = query.Select(x => new { x.equipamentID, x.Category.categoryTitle,x.Department.title })
                    .ToList() // .AsEnumerable() whatever
                    .Select(x => new { 
                        id = x.equipamentID,
                        cell = new string[] {
                            x.equipamentID.ToString(),
                            x.categoryTitle,
                            x.title
                        }})
                    .ToArray(),
    };

    return Json(result, JsonRequestBehavior.AllowGet);

}

3

请查看另一个答案中的代码示例,希望对您有所帮助。

小提示:

  1. sortname: 'Id' 是错误的参数,因为您没有名为“Id”的列。可能是 sortname:'equipmentID'
  2. 您应该删除 jqGrid 的 imgpath: '/scripts/themes/coffee/images' 参数,因为它已经弃用
  3. 您应该从 HTML 代码中删除除 id 以外的所有属性:<table id="list"></table><div id="pager"></div>

谢谢你的建议,Oleg。不幸的是,那个答案并没有真正帮助我,我仍然无法将equipmentID转换为字符串:( - tcode
@tgriffiths:你能包含Equipment类的声明吗?在另一条评论中,你写道e.equipmentID的类型为int,并且你说错误出现在e.equipmentID.ToString()中。另一方面,你有关于'System.String ToString()'方法的错误信息。其中一些信息是错误的。尝试注释掉带有e.equipmentID.ToString()的行,并验证是否没有错误。 - Oleg
@tgriffiths。我给你发了我的旧答案的参考,因为你现在的代码没有分页或排序。你还使用了 total = 1。参考答案展示了如何实现分页和排序。 - Oleg
谢谢 Oleg,但是 Kim 已经把它搞定了。感谢您的时间。 - tcode

0

我将讨论关于在ASP.NET MVC 3和Razor C#中如何解决jqGrid的行内编辑和添加新行问题。我还将包括C#控制器代码来填充网格并保存数据到网格中。首先,让我们看看如何使用NuGet软件包管理器在MVC3 Web应用程序中安装jqGrid 4.4.1。

  1. 安装jQuery 1.7.2或更高版本。
  2. 安装jQuery.UI.Combined。
  3. 安装jqGrid 4.4.1

您可以从以下网址单独下载jqGrid

http://www.trirand.com/blog/?page_id=6

jqGrid 的文档可以在以下链接找到:

http://www.trirand.com/jqgridwiki/doku.php

我不会在这篇文章中测试代码,但它基于可行的代码。我将采用蛮力方法来解决从操作方法填充jqGrid的困难和复杂问题,编辑单个行或添加新的可编辑行,然后将该行保存到操作方法。我相信可以找到更优化的方法,但这是一个很好的起点。我不会向您展示如何调整jqGrid的外观,我会留给您自己去做。我将使用JSON作为jqGrid和ASP.NET MVC 3之间的数据交换格式。我不会处理在网格中删除行的问题。

让我们从控制器中的GET操作方法开始。

public JsonResult GetProduct(int productId = 0)
{
    var productsQuery = dbContext.FirstOrDefault(p => p.ProductId == productId);
    var productsList = new List<Products>();

    // SQL does not understand ToString() so we have to do this or something like it
    foreach(var p in productsQuery)
    {
        var product = new Product{
           ProductId = p.ProductId,
           Product.Name = p.Name,
           Product.Date = p.Date.ToShortDateString()
           // and so on...
        };
        productsList.Add(product);
    }

    // You must build an anonymous object that can then be converted into a 2-dimensional 
    // array formatted for jqGrid, convert it to a 2d array then Json.  Note that all grid 
    // data must be in string format.
    var jsonData = new {
        total = 1,
        page = 1,
        records = productsQuery.Count(),
        rows = productsList.Select(p => new {
            id = p.id.ToString(),
            cell = new string[] {
                p.Name,
                p.Date.ToShortDateString(),
                // and so on...
               }
            }).ToArray();
        };

       return Json(jsonData, JsonRequestBehavior.AllowGet);
}

还有视图...

<script type="text/javascript">
    $(document).ready(function () {

        var lastSelectedId;
        var grid = $('#grid');
        grid.jqGrid({
            url: "@Url.Action("GetProducts", "Products")",
            datatype: 'json',
            mtype: 'post',
            colNames: ['ProductId', 'Name', 'Date',
                // and so on...
                ],
            colModel: [
                { name: 'ProductId', index: 'ProductId', editable: false },
                { name: 'Name', index: 'Name', editable: true, edittype: 'text' },
                { name: 'Date', index: 'Date', editable: true, edittype: 'text' }
                // and so on...
                ],
            onSelectRow: function(rowid) {
                if (rowid && rowid !== lastSelectedId) {
                    grid.jqGrid('resotreRow', lastSelectedId);
                    lastSelectedId = rowid;
                }
                grid.jqGrid('editRow', rowid, { keys: true });
            },
            editurl: "@Url.Action("SaveProducts", "Products");
            rownum: [10],
            rowList: [5,10,20,50],
            pager: '#grid_pager',
            sortName: 'Name',
            viewrecords: true,
            gridview: true,
            caption: 'Sample Grid'
    });
    grid.jqGrid('navGrid', '#pager', { edit: false, add: false: del: false,
         refresh: false });
    grid.jqGrid('inlineNav', '#pager', {
        addParams: {
            position: 'first',
            addRowParams: {
                keys: true,
                oneditfunc: onInlineEdit
            }
            add: true,
            edit: false,
            save: false,
            cancel: true
    });
    function onInlineEdit(rowid) {
        // add inline editing functionality here
    }             
</script>
@using (Html.BeginForm("","", FormMethod.Post, new { id = "ProductsForm" }))
{
    <table id="grid">
    </table>
    <div id="pager">
    </div>
}

然后是POST方法

[HttpPost]
public JsonResult SaveProduct(FormCollection frm)
{
    Product product;

    if (frm["oper"] == "add")
    {
        product = new Product();
    }
    else
    {
        int productId = Int32.Parse(frm["id"]);
        product = dbContext.Products.FirstOrDefault(p => p.ProductId == productId);
    }

    foreach (var key in frmAllKeys)
    {
        switch(key)
        {
            case "Name":
                product.Name = frm[key];
                break;
            case "Date":
                product.Date = DateTime.Parse(frm[key]);
                break;
            // and so on...
        }
    }

    try
    {
        if (frm["oper"] == "add")
        {
            dbContext.AddObject(product);
        }
        dbContext.SaveChanges();
    }
    catch (Exception ex)
    {
        Debug.WriteLine(exception.StackTrace);
        return Json(false);
    }
    return Json(true);
}

有更好的方法来做这件事,但这是一个不错的开端。我没有解决动态网格问题,我不确定如何完成。可以说,动态 jqGrid 需要更多的 JavaScript 和/或 C# 代码。建议查看 jqGrid 中的“网格中的网格”功能,将静态网格与动态网格结合起来。

我尝试构建功能来接受对象类型、记录列表并生成 jqGrid 数组和网格的 Json 数据,而无需执行上面显示的所有额外工作。我认为可以使用反射来完成,但现在没有时间。

最后,我还尝试构建功能,仅凭借对象类型和 FormCollection 从中提取数据并填充对象。同样,我认为可以使用反射来完成,但现在没有时间。如果有人想尝试构建 MVC3 C# jqGrid Json 生成器和提取器,建议使用实体框架 Code First 方法,使用 POCO 类来作为您的模型。对于这样的任务,POCO 类比实体对象更易于使用。

希望这有所帮助 :)


0
啊,我找到问题了。在LINQ to Entity中,.ToString不起作用。是的,这很奇怪,我认为非常愚蠢。但这就是核心问题。至于解决方法......当JSON序列化东西时,它们最终看起来非常像一个字符串,直到jQuery开始读取它们。因此,基本上,您应该能够完全省略.ToString(),并且它应该可以正常工作。

当我省略掉.ToString()时,e.equipmentID再次出现错误,它说:“无法将类型'int'隐式转换为'string'”。 - tcode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接