ASP.Net MVC 3 JQGrid

Прочитав об элементе управления JQGrid, я решил, что было бы хорошо использовать его в одном из моих веб-приложений ASP.Net MVC 3.

Сначала я следовал руководству Фила Хакса http://haacked.com/archive/2009/04/14/using-jquery-grid-with-asp.net-mvc.aspx, и все это хорошо. Затем я попытался реализовать что-то подобное в своем приложении, с той лишь разницей, что я использую Linq To Entities.

На странице My 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>

Then in my controller, I have the following method which is suppose to return the Json data

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

Кто-нибудь знает, как исправить эту ошибку? И также, правильно ли я делаю это или мне следует делать это иначе, чем объяснение Фила Хаака, поскольку он использует Linq to SQL?

Любая обратная связь будет очень признательна.

Спасибо, ребята.


person tcode    schedule 23.02.2011    source источник
comment
в какой строке кода возникает ошибка? Потому что, по моему мнению, похоже, что это происходит в вашем контроллере (единственное место, где я вижу метод .ToString ())   -  person guildsbounty    schedule 23.02.2011
comment
Да, ты прав. Приложение падает на e.equipment.ToString (). Какие-нибудь решения? Спасибо.   -  person tcode    schedule 23.02.2011
comment
что такое тип данных e.equipmentID? Если это уже строка, это может быть вашей проблемой. В качестве альтернативы, если это что-то, что не имеет встроенной функциональности .toString (), например, пользовательский тип данных, это также может быть вашей проблемой.   -  person guildsbounty    schedule 23.02.2011
comment
e.equipmentID имеет тип int, его нужно преобразовать в строку типа, поэтому я попробовал .ToString ()   -  person tcode    schedule 23.02.2011


Ответы (4)


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

}
person Kim Tranjan    schedule 23.02.2011

Взгляните на пример кода из другой ответ. Надеюсь, это будет полезно.

Небольшие замечания:

  1. sortname: 'Id' - неверный параметр, потому что у вас нет столбца с именем "Id". Вы, наверное, имеете в виду sortname:'equipmentID'.
  2. Вам следует удалить imgpath: '/scripts/themes/coffee/images' параметр jqGrid, который отключен.
  3. Вы должны удалить все атрибуты, кроме id из HTML-кода: <table id="list"></table><div id="pager"></div>
person Oleg    schedule 23.02.2011
comment
Спасибо за предложения Олег. К сожалению, этот другой ответ мне не очень помогает, у меня все еще проблема с преобразованием идентификатора оборудования в строку :( - person tcode; 23.02.2011
comment
@tgriffiths: Не могли бы вы включить объявление класса Equipment? В другом комментарии вы написали, что e.equipmentID имеет тип int, и вы говорите, что ошибка находится в e.equipmentID.ToString(). С другой стороны, у вас есть сообщение об ошибке 'System.String ToString()' method. Кое-что из информации неверно. Попробуйте прокомментировать строку с помощью e.equipmentID.ToString() и убедитесь, что у вас не будет ошибки. - person Oleg; 23.02.2011
comment
@tgriffiths. Я отправил вам ссылку на свой старый ответ, потому что текущий код не выполняет подкачку или сортировку. Вы также используете total = 1. В указанном ответе показано, как реализовать разбиение на страницы и сортировку. - person Oleg; 23.02.2011
comment
Спасибо, Олег, но у Ким все заработало. Спасибо, что уделили время. - person tcode; 23.02.2011

Ах, я нашел проблему. .ToString не работает в LINQ to Entity. Да, это странно и ИМО очень глупо. Но это основная проблема. Что касается обходного пути ... когда JSON сериализует вещи, они все равно очень похожи на строку, когда jQuery начинает их читать. Итак, по сути, вы должны иметь возможность полностью исключить .ToString (), и он должен работать.

person guildsbounty    schedule 23.02.2011
comment
Когда я опускаю .ToString (), в e.equipmentID снова появляется сообщение об ошибке, в котором говорится: «Невозможно неявно преобразовать тип int в строку». - person tcode; 23.02.2011

Я рассмотрю проблему встроенного редактирования и добавления новой строки в jqGrid, поскольку это применимо к ASP.NET MVC 3 и Razor C #. Я также включу код контроллера C # для заполнения сетки и сохранения данных в сетке. Сначала давайте посмотрим, как установить jqGrid 4.4.1 в веб-приложение MVC3 с помощью диспетчера пакетов NuGet.

  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 и заполняла объект, учитывая только тип объекта и FormCollection. Опять же, я думаю, что это можно сделать с помощью отражения, но сейчас у меня нет времени на это. Если кто-то хочет попытаться создать генератор и экстрактор Json MVC3 C # jqGrid, я бы порекомендовал вам использовать метод Entity Framework Code First с классами POCO для вашей модели. Для такой задачи с классами POCO намного проще работать, чем с объектами сущностей.

Надеюсь, это поможет :)

person wayne.blackmon    schedule 31.10.2012