صفحه بندی و مرتب سازی خودکار اطلاعات به کمک jqGrid در ASP.NET MVC
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: سیزده دقیقه

jqGrid یکی از افزونه‌های بسیار محبوب jQuery جهت نمایش جدول مانند اطلاعات، در سمت کلاینت است. توانمندی‌های آن صرفا به نمایش ستون‌ها و ردیف‌ها خلاصه نمی‌شود. قابلیت‌هایی مانند صفحه بندی، مرتب سازی، جستجو، ویرایش توکار، تولید خودکار صفحات افزودن رکوردها، اعتبارسنجی داده‌ها، گروه بندی، نمایش درختی و غیره را نیز به همراه دارد. همچنین به صورت توکار پشتیبانی از راست به چپ را نیز لحاظ کرده‌است.
 مجوز استفاده از فایل‌های جاوا اسکریپتی آن MIT است؛ به این معنا که در هر نوع پروژه‌ای قابل استفاده است. مجوز استفاده از کامپوننت‌های سمت سرور آن که برای نمونه جهت ASP.NET MVC یک سری HTML Helper را تدارک دیده‌اند، تجاری می‌باشد. در ادامه قصد داریم صرفا از فایل‌های JS عمومی آن استفاده کنیم.


دریافت jqGrid

برای دریافت jqGrid می‌توانید به مخزن کد آن، در آدرس https://github.com/tonytomov/jqGrid/releases و یا از طریق NuGet اقدام کنید:
 PM> Install-Package Trirand.jqGrid
استفاده از NuGet بیشتر توصیه می‌شود، زیرا به صورت خودکار وابستگی‌های jQuery و همچنین jQuery UI آن‌را نیز به همراه داشته و نصب خواهد کرد.
از jQuery UI برای تولید صفحات جستجوی بر روی رکوردها و همچنین تولید خودکار صفحات ویرایش و یا افزودن رکوردها استفاده می‌کند. به علاوه آیکن‌ها، قالب و رنگ خود را نیز از jQuery UI دریافت می‌کند. بنابراین اگر قصد تغییر قالب آن‌را داشتید تنها کافی است یک قالب استاندارد دیگر jQuery UI را مورد استفاده قرار دهید.


تنظیمات اولیه فایل Layout سایت

پس از دریافت بسته‌ی نیوگت jqGrid، نیاز است فایل‌های مورد نیاز اصلی آن‌را به شکل زیر به فایل layout پروژه اضافه کرد:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    
    <link href="~/Content/themes/base/jquery.ui.all.css" rel="stylesheet" />
    <link href="~/Content/jquery.jqGrid/ui.jqgrid.css" rel="stylesheet" />
    <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <div>
        @RenderBody()
    </div>

    <script src="~/Scripts/jquery-1.7.2.min.js"></script>
    <script src="~/Scripts/jquery-ui-1.8.11.min.js"></script>
    <script src="~/Scripts/i18n/grid.locale-fa.js"></script>
    <script src="~/Scripts/jquery.jqGrid.min.js"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>
فایل jquery.ui.all.css شامل تمامی فایل‌های CSS مرتبط با jQuery UI است و نیازی نیست تا سایر فایل‌های آن‌را لحاظ کرد.
این گرید به همراه فایل زبان فارسی grid.locale-fa.js نیز می‌باشد که در کدهای فوق پیوست شده‌است. البته اگر فرصت کردید نیاز است کمی ترجمه‌های آن بهبود پیدا کنند.


تنظیمات ثانویه site.css

.ui-widget {
}

/*how to move jQuery dialog close (X) button from right to left*/
.ui-jqgrid .ui-jqgrid-caption-rtl {
    text-align: center !important;
}

.ui-dialog .ui-dialog-titlebar-close {
    left: .3em !important;
}

.ui-dialog .ui-dialog-title {
    margin: .1em 0 .1em .8em !important;
    direction: rtl !important;
    float: right !important;
}
احتمالا تنظیمات قلم‌های jQuery UI و یا jqGrid مدنظر شما نیستند و نیاز به تعویض دارند. در اینجا نحوه‌ی بازنویسی آن‌ها را ملاحظه می‌کنید.
همچنین محل قرار گیری دکمه‌ی بسته شدن دیالوگ‌ها و راست به چپ کردن عناوین آن‌ها نیز در اینجا قید شده‌اند.


مدل برنامه

در ادامه قصد داریم لیستی از محصولات را با ساختار ذیل، توسط jqGrid نمایش دهیم:
namespace jqGrid01.Models
{
    public class Product
    {
        public int Id { set; get; }
        public string Name { set; get; }
        public decimal Price { set; get; }
        public bool IsAvailable { set; get; }
    }
}


ساختار داده‌ای مورد نیاز توسط jqGrid

jqGrid مستقل است از فناوری سمت سرور. بنابراین هر چند در عنوان بحث ASP.NET MVC ذکر شده‌است، اما از ASP.NET MVC صرفا جهت بازگرداندن خروجی JSON استفاده خواهیم کرد و این مورد در هر فناوری سمت سرور دیگری نیز می‌تواند انجام شود.
using System.Collections.Generic;

namespace jqGrid01.Models
{
    public class JqGridData
    {
        public int Total { get; set; }

        public int Page { get; set; }

        public int Records { get; set; }

        public IList<JqGridRowData> Rows { get; set; }

        public object UserData { get; set; }
    }

    public class JqGridRowData
    {
        public int Id { set; get; }
        public IList<string> RowCells { set; get; }
    }
}
خروجی JSON مدنظر توسط jqGrid، یک چنین ساختاری را باید داشته باشد.
Total، نمایانگر تعداد صفحات اطلاعات است. عدد Page، شماره صفحه‌ی جاری است. عدد Records، تعداد کل رکوردهای گزارش را مشخص می‌کند. ساختار ردیف‌های آن نیز تشکیل شده‌است از یک Id به همراه سلول‌هایی که باید با فرمت string، بازگشت داده شوند.
UserData اختیاری است. برای مثال اگر خواستید جمع کل صفحه را در ذیل گرید نمایش دهید، می‌توانید یک anonymous object را در اینجا مقدار دهی کنید. خاصیت‌های آن دقیقا باید با نام خاصیت‌های ستون‌های متناظر، یکی باشند. برای مثال اگر می‌خواهید عددی را در ستون Id، در فوتر گرید نمایش دهید، باید نام خاصیت را Id ذکر کنید.


کدهای سمت کلاینت گرید

در اینجا کدهای کامل سمت کلاینت گرید را ملاحظه می‌کنید:
@{
    ViewBag.Title = "Index";
}

<div dir="rtl" align="center">
    <div id="rsperror"></div>
    <table id="list" cellpadding="0" cellspacing="0"></table>
    <div id="pager" style="text-align:center;"></div>
</div>

@section Scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            $('#list').jqGrid({
                caption: "آزمایش اول",
                //url from wich data should be requested
                url: '@Url.Action("GetProducts","Home")',
                //type of data
                datatype: 'json',
                jsonReader: { 
                    root: "Rows",
                    page: "Page",
                    total: "Total",
                    records: "Records",
                    repeatitems: true,
                    userdata: "UserData",
                    id: "Id",
                    cell: "RowCells"
                },
                //url access method type
                mtype: 'GET',
                //columns names
                colNames: ['شماره', 'نام محصول', 'موجود است', 'قیمت'],
                //columns model
                colModel: [
                { name: 'Id', index: 'Id', align: 'right', width: 50, sorttype: "number" },
                { name: 'Name', index: 'Name', align: 'right', width: 300 },
                { name: 'IsAvailable', index: 'IsAvailable', align: 'center', width: 100, formatter: 'checkbox' },
                { name: 'Price', index: 'Price', align: 'center', width: 100, sorttype: "number" }
                ],
                //pager for grid
                pager: $('#pager'),
                //number of rows per page
                rowNum: 10,
                rowList: [10, 20, 50, 100],
                //initial sorting column
                sortname: 'Id',
                //initial sorting direction
                sortorder: 'asc',
                //we want to display total records count
                viewrecords: true,
                altRows: true,
                shrinkToFit: true,
                width: 'auto',
                height: 'auto',
                hidegrid: false,
                direction: "rtl",
                gridview: true,
                rownumbers: true,
                footerrow: true,
                userDataOnFooter: true,
                loadComplete: function() {
                    //change alternate rows color
                    $("tr.jqgrow:odd").css("background", "#E0E0E0");
                },
                loadError: function(xhr, st, err) {
                     jQuery("#rsperror").html("Type: " + st + "; Response: " + xhr.status + " " + xhr.statusText);
                }
                //, loadonce: true
            })
            .jqGrid('navGrid', "#pager",
            {
                edit: false, add: false, del: false, search: false,
                refresh: true
            })
            .jqGrid('navButtonAdd', '#pager',
            {
                caption: "تنظیم نمایش ستون‌ها", title: "Reorder Columns",
                onClickButton: function() {
                     jQuery("#list").jqGrid('columnChooser');
                }
            });
        });
    </script>
}
- برای نمایش این گرید، به یک جدول و یک div نیاز است. از جدول با id مساوی list جهت نمایش رکوردهای برنامه استفاده می‌شود. از div با id مساوی pager برای نمایش اطلاعات صفحه بندی و نوار ابزار پایین گرید کمک گرفته خواهد شد.
Div سومی با id مساوی rsperror نیز تعریف شده‌است که از آن جهت نمایش خطاهای بازگشت داده شده از سرور استفاده کرده‌ایم.
- در ادامه نحوه‌ی فراخوانی افزونه‌ی jqGrid را بر روی جدول list ملاحظه می‌کنید.
- خاصیت caption، عنوان نمایش داده شده در بالای گرید را مقدار دهی می‌کند:


- خاصیت url، به آدرسی اشاره می‌کند که قرار است ساختار JqGridData ایی را که پیشتر در مورد آن بحث کردیم، با فرمت JSON بازگشت دهد. در اینجا برای مثال به یک اکشن متد کنترلری در یک پروژه‌ی ASP.NET MVC اشاره می‌کند.
- datatype را برابر json قرار داده‌ایم. از نوع xml نیز پشتیبانی می‌کند.
- شیء jsonReader را از این جهت مقدار دهی کرده‌ایم تا بتوانیم شیء JqGridData را با اصول نامگذاری دات نت، هماهنگ کنیم. برای درک بهتر این موضوع، فایل jquery.jqGrid.src.js را باز کنید و در آن به دنبال تعریف jsonReader بگردید. به یک چنین مقادیر پیش فرضی خواهید رسید:
ts.p.jsonReader = $.extend(true,{
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: true,
cell: "cell",
id: "id",
userdata: "userdata",
subgrid: {root:"rows", repeatitems: true, cell:"cell"}
},ts.p.jsonReader);
برای مثال سلول‌ها را با نام cell دریافت می‌کند که در شیء JqGridData به RowCells تغییر نام یافته‌است. برای اینکه این تغییر نام‌ها توسط jqGrid پردازش شوند، تنها کافی است jsonReader را مطابق تعاریفی که ملاحظه می‌کنید، مقدار دهی کرد.
- در ادامه mtype به GET تنظیم شده‌است. در اینجا مشخص می‌کنیم که عملیات Ajax ایی دریافت اطلاعات از سرور توسط GET انجام شود یا برای مثال توسط POST.
- خاصیت colNames، معرف نام ستون‌های گرید است. برای اینکه این نام‌ها از راست به چپ نمایش داده شوند، باید خاصیت direction به rtl تنظیم شود.
- colModel آرایه‌ای است که تعاریف ستون‌ها را در بر دارد. مقدار name آن باید یک نام منحصربفرد باشد. از این نام در حین جستجو یا ویرایش اطلاعات استفاده می‌شود. مقدار index نامی است که جهت مرتب سازی اطلاعات، به سرور ارسال می‌شود. تنظیم sorttype در اینجا مشخص می‌کند که آیا به صورت پیش فرض، ستون جاری رشته‌ای مرتب شود یا اینکه برای مثال عددی پردازش گردد. مقادیر مجاز آن text (مقدار پیش فرض)، float، number، currency، numeric، int ، integer، date و datetime هستند.
- در ستون IsAvailable، مقدار formatter نیز تنظیم شده‌است. در اینجا توسط formatter، نوع bool دریافتی با یک checkbox نمایش داده خواهد شد.
- خاصیت pager به id متناظری در صفحه اشاره می‌کند.
- توسط rowNum مشخص می‌کنیم که در هر صفحه چه تعداد رکورد باید نمایش داده شوند.
- تعداد رکوردهای نمایش داده شده را می‌توان توسط rowList پویا کرد. در اینجا آرایه‌ای را ملاحظه می‌کنید که توسط اعداد آن، کاربر امکان انتخاب صفحاتی مثلا 100 ردیفه را نیز پیدا می‌کند. rowList به صورت یک dropdown در کنار عناصر راهبری صفحه در فوتر گرید ظاهر می‌شود.
- خاصیت sortname، نحوه‌ی مرتب سازی اولیه گرید را مشخص می‌کند.
- خاصیت sortorder، جهت مرتب سازی اولیه‌ی گردید را تنظیم می‌کند.
- viewrecords: تعداد رکوردها را در نوار ابزار پایین گرید نمایش می‌دهد.
- altRows: سبب می‌شود رنگ متن ردیف‌ها یک در میان متفاوت باشد.
- shrinkToFit: به معنای تنظیم خودکار اندازه‌ی سلول‌ها بر اساس اندازه‌ی داده‌ای است که دریافت می‌کنند.
- width: عرض گرید، که در اینجا به auto تنظیم شده‌است.
- height: طول گرید، که در اینجا به auto جهت محاسبه‌ی خودکار، تنظیم شده‌است.
- gridview: برای بالا بردن سرعت نمایشی به true تنظیم شده‌است. در این حالت کل ردیف یکباره درج می‌شود. اگر از subgird یا حالت نمایش درختی استفاده شود، باید این خاصیت را false کرد.
- rownumbers: ستون سمت راست شماره ردیف‌های خودکار را نمایش می‌دهد.
- footerrow: سبب نمایش ردیف فوتر می‌شود.
- userDataOnFooter: سبب خواهد شد تا خاصیت UserData مقدار دهی شده، در ردیف فوتر ظاهر شود.
- loadComplete : یک callback است که زمان پایان بارگذاری صفحه‌ی جاری را مشخص می‌کند. در اینجا با استفاده از jQuery سبب شده‌ایم تا رنگ پس زمینه‌ی ردیف‌ها یک در میان تغییر کند.
- loadError: اگر از سمت سرور خطایی صادر شود، در این callback قابل دریافت خواهد بود.
- در ادامه توسط فراخوانی متد jqGrid با پارامتر navGrid، در ناحیه pager سبب نمایش دکمه refresh شده‌ایم. این دکمه سبب بارگذاری مجدد اطلاعات گردید از سرور می‌شود.
- همچنین به کمک متد jqGrid با پارامتر navButtonAdd در ناحیه pager، سبب نمایش دکمه‌ای که صفحه‌ی انتخاب ستون‌ها را ظاهر می‌کند، خواهیم شد.



پیشنیاز کدهای سمت سرور jqGrid

اگر به تنظیمات گرید دقت کرده باشید، خاصیت index ستون‌ها، نامی است که به سرور، جهت اطلاع رسانی در مورد فیلتر اطلاعات و مرتب سازی مجدد آن‌ها ارسال می‌گردد. این نام، بر اساس کلیک کاربر بر روی ستون‌های موجود، هر بار می‌توان متفاوت باشد. بنابراین بجای if و else نوشتن‌های طولانی جهت مرتب سازی اطلاعات، می‌توان از کتابخانه‌ی معروفی به نام dynamic LINQ استفاده کرد.
 PM> Install-Package DynamicQuery
به این ترتیب می‌توان قسمت orderby را به صورت پویا و با رشته‌ای دریافتی، مقدار دهی کرد.


کدهای سمت سرور بازگشت اطلاعات به فرمت JSON

در کدهای سمت کلاینت، به اکشن متد GetProducts اشاره شده بود. تعاریف کامل آن‌را در ذیل مشاهده می‌کنید:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using jqGrid01.Models;
using jqGrid01.Extensions; // for dynamic OrderBy

namespace jqGrid01.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult GetProducts(string sidx, string sord, int page, int rows)
        {
            var list = ProductDataSource.LatestProducts;

            var pageIndex = page - 1;
            var pageSize = rows;
            var totalRecords = list.Count;
            var totalPages = (int)Math.Ceiling(totalRecords / (float)pageSize);

            var products = list.AsQueryable()
                               .OrderBy(sidx + " " + sord)
                               .Skip(pageIndex * pageSize)
                               .Take(pageSize)
                               .ToList();

            var jqGridData = new JqGridData
            {
                UserData = new // نمایش در فوتر
                {
                    Name = "جمع صفحه",
                    Price = products.Sum(x => x.Price)
                },
                Total = totalPages,
                Page = page,
                Records = totalRecords,
                Rows = (products.Select(product => new JqGridRowData
                                                {
                                                    Id = product.Id,
                                                    RowCells = new List<string>
                                                    {
                                                        product.Id.ToString(CultureInfo.InvariantCulture),
                                                        product.Name,
                                                        product.IsAvailable.ToString(),
                                                        product.Price.ToString(CultureInfo.InvariantCulture)
                                                    }
                                                })).ToList()
            };
            return Json(jqGridData, JsonRequestBehavior.AllowGet);
        }
    }
}
- سطر ProductDataSource.LatestProducts چیزی نیست بجز لیست جنریکی از محصولات.
- امضای متد GetProducts نیز مهم است. دقیقا همین پارامترها با همین نام‌ها از طرف jqGrid به سرور ارسال می‌شوند که توسط آن‌ها ستون مرتب سازی، جهت مرتب سازی، صفحه‌ی جاری و تعداد ردیفی که باید بازگشت داده شوند، قابل دریافت است.
- در این کدها دو قسمت مهم وجود دارند:
الف) متد OrderBy نوشته شده، به صورت پویا عمل می‌کند و از کتابخانه‌ی Dynamic LINQ مایکروسافت بهره می‌برد.
به علاوه توسط Take و Skip کار صفحه بندی و بازگشت تنها بازه‌ای از اطلاعات مورد نیاز، انجام می‌شود.
ب) لیست جنریک محصولات، در نهایت باید با فرمت JqGridData به صورت JSON بازگشت داده شود. نحوه‌ی این Projection را در اینجا می‌توانید ملاحظه کنید.
هر ردیف این لیست، باید تبدیل شود به ردیفی از جنس JqGridRowData، تا توسط jqGrid قابل پردازش گردد.
- توسط مقدار دهی UserData، برچسبی را در ذیل ستون Name و مقداری را در ذیل ستون Price نمایش خواهیم داد.


برای مطالعه‌ی بیشتر

بهترین راهنمای جزئیات این Grid، مستندات آنلاین آن هستند: http://www.trirand.com/jqgridwiki/doku.php?id=wiki:jqgriddocs
همچنین این مستندات را با فرمت PDF نیز می‌توانید مطالعه کنید: http://www.trirand.com/blog/jqgrid/downloads/jqgriddocs.pdf


کدهای کامل این مثال را از اینجا می‌توانید دریافت کنید
jqGrid01.zip
 

مثال‌های سری jqGrid تغییرات زیادی داشتند. برای دریافت آن‌ها به این مخزن کد مراجعه کنید. 
  • #
    ‫۱۰ سال و ۳ ماه قبل، چهارشنبه ۱۱ تیر ۱۳۹۳، ساعت ۱۸:۰۳
    امکان دارد شکل گرید را بصورت  گرید بوت استرپ نمایش داد ؟
    • #
      ‫۱۰ سال و ۳ ماه قبل، چهارشنبه ۱۱ تیر ۱۳۹۳، ساعت ۱۸:۴۰
      همانطور که در بحث عنوان شد، قالب این گرید از jQuery UI تامین می‌شود. بنابراین هر نوع قالب نوشته شده‌ای برای jQuery UI با آن سازگار است؛ مانند:
      - jQuery UI Bootstrap
      - jqGrid.bootstrap  
  • #
    ‫۱۰ سال و ۳ ماه قبل، چهارشنبه ۱۱ تیر ۱۳۹۳، ساعت ۲۳:۵۱
    متاسفانه در حالت rtl تغییر اندازه‌ی ستون‌ها با باگ همراه هست.
    • #
      ‫۱۰ سال و ۳ ماه قبل، پنجشنبه ۱۲ تیر ۱۳۹۳، ساعت ۰۰:۳۶
      چه مشکلی دقیقا؟
      • #
        ‫۱۰ سال و ۳ ماه قبل، پنجشنبه ۱۲ تیر ۱۳۹۳، ساعت ۰۱:۰۰
        مثلا در اینجا سایز ستون Id را بیشتر کردم، ردیف‌های متناظرش باهاش هماهنگ نیستند.( با موس اندازه‌ی ستون را تغییر دهیم)

        • #
          ‫۱۰ سال و ۳ ماه قبل، پنجشنبه ۱۲ تیر ۱۳۹۳، ساعت ۰۱:۲۱
          درسته. البته فقط با کروم 35 اینطوری هست. با 11 IE و فایرفاکس 30 تست کردم مشکلی نبود.
          • #
            ‫۱۰ سال و ۳ ماه قبل، پنجشنبه ۱۲ تیر ۱۳۹۳، ساعت ۰۴:۱۳
            خیلی عالی. خیلی وقته که دنبال یک دیتا گرید می‌گردم تا مشکلی نداشته باشه. برای AngularJS یک Datagrid هست به نام ng-grid که خیلی خوب و کامل هست ولی rtl را خوب ساپورت نمی‌کنه. نسخه‌ی rtl هم که یه نفر براش نوشته باگهای زیادی داره مثل همین تغییر سایز ستون ها.
            در کل سوالم این هست که باگ تغییر سایز ستون jqGrid از کروم هست یا خود jqGrid؟ چون می‌خوام از ng-grid کوچ کنم به jq-grid و  ببینم ارزش این مهاجرت را داره یا نه.
            • #
              ‫۱۰ سال و ۳ ماه قبل، پنجشنبه ۱۲ تیر ۱۳۹۳، ساعت ۰۴:۴۹
              به نظر کروم در هر نگارشی نحوه‌ی تشخیص آن فرق می‌کند و این مساله مشکلاتی را به همراه داشته. بحثی در این مورد.
        • #
          ‫۹ سال و ۱۲ ماه قبل، چهارشنبه ۲ مهر ۱۳۹۳، ساعت ۱۷:۵۱
          برای رفع این مشکل فقط کافی است .ui-jqgrid .ui-jqgrid-hbox-rtl را در فایل css آن یافته و تبدیل کنید به:
          .ui-jqgrid .ui-jqgrid-hbox-rtl {float: right; padding-left: 0;}
  • #
    ‫۱۰ سال و ۳ ماه قبل، سه‌شنبه ۱۷ تیر ۱۳۹۳، ساعت ۰۲:۴۳
    وقتی این کتاب خانه (Install-Package DynamicQuery  ) رو اضافه کردم پوشه‌ی به نام Extensions و کلاسی به نام LinqExtensions.cs نساخت فقط چیزی که در تصویر زیر میبینید ساخته ؟ چکار باید بکنم ؟

    • #
      ‫۱۰ سال و ۳ ماه قبل، سه‌شنبه ۱۷ تیر ۱۳۹۳، ساعت ۰۳:۱۵
      این بسته، کامپایل شده‌ی آن فایل را تحت عنوان Dynamic.dll به لیست ارجاعات پروژه اضافه می‌کند. فایل Dynamic Expressions.html هم راهنمای آن است. به عبارتی همه چیز آماده است؛ از فضای نام جدید System.Linq.Dynamic آن استفاده کنید.
  • #
    ‫۱۰ سال و ۳ ماه قبل، شنبه ۲۱ تیر ۱۳۹۳، ساعت ۱۹:۵۷
    سلام
    آیا می‌شه ستون هایی که عدم نمایش آنها انتخاب شده اند را از طریق یک پارامتر در getproducts گرفت
    اگر می‌شه چه طوری ؟
    • #
      ‫۱۰ سال و ۳ ماه قبل، شنبه ۲۱ تیر ۱۳۹۳، ساعت ۲۳:۲۶
      columnChooser رویداد done هم دارد که از آن می‌شود برای آنالیز ستون‌ها استفاده کرد:
                  .jqGrid('navButtonAdd', '#pager',
                  {
                      caption: "تنظیم نمایش ستون‌ها", title: "Reorder Columns",
                      onClickButton: function () {
                          jQuery("#list").jqGrid('columnChooser', {
                              done: function (perm) {
                                  if (perm) {
                                      $("#list").jqGrid("remapColumns", perm, true, false);
                                  }
      
                                  var colModel = $("#list").jqGrid('getGridParam', 'colModel');
                                  var hiddenColumns = new Array();
                                  for (var i = 0; i < colModel.length; i++) {
                                      if (colModel[i].hidden) {
                                          hiddenColumns.push(colModel[i].name);
                                      }
                                  }
      
                                  $.ajax({
                                      type: "POST",
                                      url: "@Url.Action("HiddenColumns","Home")",
                                      dataType: "json",
                                      traditional: true,
                                      data: { hiddenColumns: hiddenColumns }
                                  });
                              }
                          });
                      }
                  })
      متد getGridParam با پارامتر colModel، آرایه‌ای از خواص ستون‌ها را بر می‌گرداند.
      var colModel = $("#list").jqGrid('getGridParam', 'colModel');
      در این خواص اگر hidden مساوی true بود، یعنی مخفی شده‌است. در نهایت از این‌ها می‌شود یک آرایه را تشکیل داد و به سرور ارسال کرد:
              public ActionResult HiddenColumns(string[] hiddenColumns)
              {
                  //todo: save it in the DB or cookies or session ....
      
                  return Content("OK");
              }
      امضای اکشن متدی است که لیست نام ستون‌های مخفی را دریافت می‌کند.
      • #
        ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۲۲ تیر ۱۳۹۳، ساعت ۱۴:۰۰
        خیلی مچکرم؛ من می‌خواستم بدونم آیا می‌تونم بدون فرستادن لیست ستون‌های پنهان شده به یک اکشن دیگر و در نتیچه ذخیره کردن آن بر روی کوکی و یا دیتابیس و یا روش‌های دیگر مستقیم در اکشن GetProducts بگیرتش، اگر بخوام شفاف‌تر بگم ، من می‌خوام وقتی کاربر دکمه خروجی پی دی اف رو زد ستون‌های گرید رو کاربر قبلش تنظیم کرده باشه و در پی دی اف مورد نظر ستون‌های حذف شده رو دیگر نبینه همچنین با در نظر گرفتن موارد فیلتر شده در گرید .
        • #
          ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۲۲ تیر ۱۳۹۳، ساعت ۱۶:۳۲
          برای ارسال پارامترهای دلخواه به سرور از خاصیت postData استفاده کنید:
                  function getHiddenColumnsList() {
                      var colModel = $("#list").jqGrid('getGridParam', 'colModel');
                      var hiddenColumns = new Array();
                      
                      if (!colModel)
                          return hiddenColumns;
          
                      for (var i = 0; i < colModel.length; i++) {
                          if (colModel[i].hidden) {
                              hiddenColumns.push(colModel[i].name) ;
                          }
                      }
                      return hiddenColumns;
                  }
          
                $(document).ready(function () {
                      $('#list').jqGrid({
                              // ... 
                              postData: { 'hiddenColumns': function() { return getHiddenColumnsList(); } }
                              // ... 
                          });
                 });
          سمت سرور در اکشن متد GetProducts، خاصیت جدید hiddenColumns به صورت یک رشته که عناصر آن با کاما از هم جدا شده‌اند، قابل دریافت و آنالیز است.
          و برای گزارش‌گیری با Pdf Report در تعریف ستون‌ها (مثلا ستون Id):
          column.IsVisible(hiddenColumns.Split(',').All(col => col != "Id"));

          یک نکته: ذکر function در postData ضروری است؛ وگرنه فقط یکبار محاسبه می‌شود.
  • #
    ‫۱۰ سال و ۲ ماه قبل، جمعه ۱۰ مرداد ۱۳۹۳، ساعت ۲۰:۰۲
    سلام خسته نباشید. فایل‌های پروژه‌هاتون را که دانلود میکنم، وقتی اجرا میکنم ارور زیر را میدهد:
    Could not load file or assembly 'System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
    دلیلش چیه؟
     
    • #
      ‫۱۰ سال و ۲ ماه قبل، جمعه ۱۰ مرداد ۱۳۹۳، ساعت ۲۲:۰۳
      - ابتدا به اینترنت وصل شوید.
      - سپس در خط فرمان پاورشل نیوگت (^ و ^) دستور زیر را اجرا کنید:
      PM> update-package -reinstall
      به این صورت بسته‌های MVC 5 آن به صورت صحیح به پروژه اضافه می‌شوند.  
      • #
        ‫۱۰ سال و ۲ ماه قبل، شنبه ۱۱ مرداد ۱۳۹۳، ساعت ۱۵:۳۳
        با mvc5 باید باشه ؟ من mvc 4 دارم 
        • #
          ‫۱۰ سال و ۲ ماه قبل، شنبه ۱۱ مرداد ۱۳۹۳، ساعت ۱۵:۵۱
          خیر. یک پروژه خالی MVC4 ایجاد کنید. بعد پوشه‌ها و فایل‌های این پروژه را در آن اضافه کنید (منهای فایل‌های کانفیگ)؛ کار می‌کند.
          jqGrid هیچگونه وابستگی به فناوری‌های سمت سرور ندارد. با وب فرم‌ها قابل استفاده است. با PHP هم قابل استفاده است. در اینجا از MVC فقط برای بازگشت اطلاعات مورد نیاز آن به فرمت JSON استفاده شده‌است. در این مثال خاص، کاربرد ویژه‌ی دیگری ندارد. می‌شد بجای آن از Web API هم استفاده کرد.
  • #
    ‫۱۰ سال و ۲ ماه قبل، سه‌شنبه ۱۴ مرداد ۱۳۹۳، ساعت ۱۸:۵۲
    سلام؛ از مثالی که زدید دارم استفاده میکنم، در کلاس ReflectionHelper  متد FindFieldType موقعی که از جداول خود ارجاع دهنده استفاده میکنیم(در اینجا جدول پست)، خطا stackoverflow می‌گیرم، کجاش رو باید چک کنیم که فراخوانی بی نهایت اتفاق نیفته؟ مگه فیلد dumplevel همچین کاری انجام نمیده؟
    data model م به این صورته : 


     
  • #
    ‫۱۰ سال و ۲ ماه قبل، دوشنبه ۲۰ مرداد ۱۳۹۳، ساعت ۲۰:۳۰
    سلام
    اگه بخوام نام ستون‌ها رو از روی مدل یا ویو بگ بخونم و دستی ننویسم باید چیکار کنم. من از مدل Database First استفاده می‌کنم. چطور میتونم اینکار رو انجام بدم
  • #
    ‫۱۰ سال و ۱ ماه قبل، پنجشنبه ۱۳ شهریور ۱۳۹۳، ساعت ۰۱:۳۷
    با سلام  و خسته نباشید من یه مشکلی داشتم می‌خواستم در صورت امکان راهنمایی نمایید : 
    توی یه صفحه می‌خوام لود شدن داده‌های این گرید با رویداد کلیک یه دکمه اتفاق بیفته یه مقدار سرچ هم زدم که تقریبا همشون می‌گفتن توی رویداد کلیک بنویسم :
     jQuery("#list").trigger("reloadGrid");
    اما با این هم جواب نداد و اصلا ActionMethod  فراخوانی نمیشه ممنون میشم راهنمایی نمایید
    • #
      ‫۱۰ سال و ۱ ماه قبل، پنجشنبه ۱۳ شهریور ۱۳۹۳، ساعت ۰۱:۵۴
      reloadGrid برای حالتی است که Grid در صفحه نمایش داده شده و موجود است. برای نمایش یک گرید با کلیک بر روی یک دکمه، کل کدهای داخل document.ready مثال فوق را داخل یک متد جداگانه قرار دهید و سپس آن‌را مستقلا فراخوانی کنید. document.ready یعنی به محض آماده شدن DOM این اطلاعات را اجرا کن.
      • #
        ‫۱۰ سال و ۱ ماه قبل، پنجشنبه ۱۳ شهریور ۱۳۹۳، ساعت ۰۲:۰۹
        راستش اولش هم همین کارو کردم جواب نگرفتم تستش هم کردم مطمئنم که رویداد کلیک  و تابع مذکور فراخوانی میشه اما متد سرور فراخوانی نمیشه
        • #
          ‫۱۰ سال و ۱ ماه قبل، پنجشنبه ۱۳ شهریور ۱۳۹۳، ساعت ۰۳:۰۸
          پس از آزمایش مشکلی مشاهده نشد.
          همانطور که عنوان شد، کل اطلاعات داخل document ready به داخل یک متد مجزا منتقل شد:
                  function loadGrid() {
                      $('#list').jqGrid({
                          caption: "آزمایش اول",
                          // .....
                      });
                  } 
          و سپس فراخوانی آن توسط یک دکمه:
          <button onclick="loadGrid()">Load Grid</button>
  • #
    ‫۱۰ سال و ۱ ماه قبل، پنجشنبه ۲۰ شهریور ۱۳۹۳، ساعت ۱۷:۳۹
    یک نکته‌ی تکمیلی
    نسخه‌ی جدید و زنده‌ی dynamic LINQ در اینجا نگهداری می‌شود.
    PM> Install-Package System.Linq.Dynamic.Library
  • #
    ‫۹ سال و ۱۱ ماه قبل، شنبه ۱۷ آبان ۱۳۹۳، ساعت ۲۱:۴۷
    با سلام
    دوستان jqGrid  برای asp رایگان هستش؟
    من دیدم نوشته این نسخه 30 روزه هستش. میشه یه نفر راهنمایی کنه؟
    • #
      ‫۹ سال و ۱۱ ماه قبل، شنبه ۱۷ آبان ۱۳۹۳، ساعت ۲۲:۵۵
      مجوز عمومی فایل‌های اسکریپت اصلی آن MIT است و در هر نوع پروژه‌ای قابل استفاده‌است. مجوز تجاری هم دارد برای حالتیکه بخواهید کامپوننت‌های ASP.NET آن‌را بخرید که ... نیازی نیست (^).
       3. Can be used in proprietary works
      The license policy allow you to use this piece of code even inside commercial (not open source)
      projects. So you can use this software without giving away your own (precious?) source code.
  • #
    ‫۹ سال و ۱۰ ماه قبل، شنبه ۸ آذر ۱۳۹۳، ساعت ۱۶:۴۰
    با تشکر از آقای نصیری
    میخواستم بدونم jqgrid امکان دیتا بایندینگ داره به صورتی که وقتی یه رکورد اضافه کردیم و اونا دادیم به گرید یه سطر اضافه کنه و یا اینکه اگه یه ردیف را ویرایش کردیم خودش رکورد ویرایش شده را به گرید بایند کنه همه اینا بدون رفتن به سرور باشه. برای اضافه و ویرایش از امکانات و فرم‌های توکار jqgrid نمیخوام استفاده کنم از فرم‌های خودم میخوام استفاده کنم.

    و آیا event ای داره وقتی که یک یا چند ردیف در گرید انتخاب شده raise بشه؟
    با تشکر
    • #
      ‫۹ سال و ۱۰ ماه قبل، شنبه ۸ آذر ۱۳۹۳، ساعت ۱۷:۱۷
      مطالب گروه jqGrid را بررسی کنید. الزامی به استفاده از فرم‌های پیش فرض آن نیست. امکان inline add/edit هم دارد به همراه سفارشی سازی جزئیات آن‌ها. در مورد رویدادهای آن هم در لابلای مباحث این گروه با ارائه کدهای مرتبط، بحث شده‌است.
  • #
    ‫۹ سال و ۱۰ ماه قبل، سه‌شنبه ۱۱ آذر ۱۳۹۳، ساعت ۱۹:۵۰
    من میخواستم jqgrid رو به بانک اطلاعاتی وصل کنم ولی اسکریپت jquery اطلاعات رو برای اکشن متدم نمیفرسته break point گذاشتم ولی اتفاقی نمیفته مشکل از چیه؟
    • #
      ‫۹ سال و ۱۰ ماه قبل، سه‌شنبه ۱۱ آذر ۱۳۹۳، ساعت ۲۰:۵۴
      - مثال کامل بحث در انتهای آن پیوست شده‌است. کار خودتان را با آن مطابقت دهید.
      - همچنین نیاز است با مباحث دیباگ اسکریپت‌ها آشنا باشید. اطلاعات بیشتر
      + آشنایی با نحوه‌ی صحیح طرح یک سؤال فنی هم در تمام سایت‌ها راهگشا است. اطلاعات بیشتر
  • #
    ‫۹ سال و ۷ ماه قبل، یکشنبه ۱۷ اسفند ۱۳۹۳، ساعت ۱۸:۴۷
    باسلام؛ من در قسمت نحوه ارتباط پایگاه داده با jqgrid مشکل دارم. در asp میامدیم DataSource گرید را مساوی با DataTable  قرار میدادیم ولی الان نمیدونم چه جوری داده‌های داخل پایگاه داده رو داخل jqGrid قرار بدم یا داده جدیدی از طریق jqgrid به پایگاه داده اضافه کنم. داده‌های من که حاصل اجرای   storeProcedure   است.  داخل یک datatable  قرار داره چه جوری میتونم jqgrid رو با اون ارتباط بدهم؟ تا داده‌های من رو نشون بده. ممنون میشم راهنماییم کنید.
    • #
      ‫۹ سال و ۷ ماه قبل، یکشنبه ۱۷ اسفند ۱۳۹۳، ساعت ۱۹:۱۴
      - یک سری micro orm مانند Dapper وجود دارند که اساس کار آن‌ها، کوئری نویسی و سپس دریافت اطلاعات از طریق لیست‌های جنریک (مانند روش نهایی کار در مثال جاری) است. بنابراین datatable را فراموش کنید و شروع کنید به استفاده از dapper یا peta poco (اگر نمی‌خواهید از Entity framework استفاده کنید).
      - مهم این نیست که منبع داده‌ی شما به چه نحوی تهیه می‌شود. مهم این است که این گرید خاص و امثال آن (Kendo UI هم به همین صورت)، داده‌ها را با فرمت JSON دریافت می‌کنند. همچنین داده‌ها را با فرمت JSON به سمت سرور ارسال می‌کنند. بنابراین مطابق مثالی که زده شد، اطلاعات خودتان را تبدیل می‌کنید به فرمت new JqGridData و سپس آن‌را به صورت JSON بازگشت می‌دهید. همچنین در سمت کاربر، تمام تغییرات، با فرمت JSON به سمت سرور ارسال می‌شوند که این مورد و آنالیز آن در قسمت‌های بعدی این سری بررسی شده‌اند.
      - در این سری مثال‌ها از امکانات توکار ASP.NET MVC برای بازگشت داده‌ها به صورت JSON استفاده شده‌است. اما jqGrid یا Kendo UI Grid و امثال آن‌ها اساسا هیچگونه وابستگی به فناوری‌های سمت سرور ندارند. بنابراین از یکی از روش‌های موجود بازگشت اطلاعات به فرمت JSON استفاده کنید. مهم هم نیست که برنامه‌ی شما ASP.NET MVC است یا وب فرم یا PHP یا هر چی. برای مثال از کتابخانه‌ی JSON.NET برای بازگشت اطلاعات به فرمت JSON استفاده کنید.
      - علاوه بر این، روش‌های دیگری هم برای بازگشت اطلاعات به فرمت JSON وجود دارند. اطلاعات بیشتر
      • #
        ‫۹ سال و ۷ ماه قبل، دوشنبه ۱۸ اسفند ۱۳۹۳، ساعت ۱۹:۴۰
         با سلام؛ خیلی ممنونم. ولی میخواستم اون کاری که میخوام انجام بدم رو بیشتر توضیح بدم تا موضوع روشن‌تر بشه

        همون طور که در عکس مشخصه من 3 تا جدول دارم
        -Programs برای نگه داری اطلاعات برنامه که به صورت تو در تو است
        -PrgElements برای نگه داری اطلاعات مربوط به المان‌های تعریف شده در برنامه (مثل فرم -منو- کنترل و ...) که ElementID به صورت HiearachyID  تعریف شده و متاسفانه Entity Framwork,LingToSql این DataType رو ساپرت نمیکنه برای همین باید  از ADO استفاده کنم.
        من میخوام گریدی داشته باشم که کاربر اطلاعات راجع به المنت‌های برنامه رو تو در تو وارد کنه و   این اطلاعات برای کاربر نمایش داده بشه تا کاربر بتونه با انتخاب سطر مربوطه اون رو ویرایش کنه حذف کنه و مورد جدیدی رو اضافه کنه 
        یک گریدی به این شکل:


        من در قسمت کدهای سمت سرور ، اون قسمتی که row رو مقدار دهی میکنید رو متاسفانه نمیتونم پیاده سازی کنم (در واقع تبدیل داده مورد نظر به فرمت jqGridData جایی که Row  رو مقدار دهی می‌کنیم)
  • #
    ‫۸ سال و ۷ ماه قبل، شنبه ۲۴ بهمن ۱۳۹۴، ساعت ۱۷:۲۲
    بسیار سپاسگذارم؛ یک سوال داشتم در این رابطه:
    در سمت سرور هنگام پر کردن داده‌ها در RowCells  برای مثال با product.Name  ما نام یک محصول را اضافه کرده ایم که البته خصیصه نام در اینجا از نوع sting می‌باشد.
    حال تصور کنید یکی از پروپرتی‌های من Enum باشد (بنده از 5 mvc استفاده میکنم) به طوری که تعریف Enum هم به صورت زیر است:

    public enum publishStatus
    {
      [Display(Name = "نمایش داده شود")]
      show = 0,
    
      [Display(Name = "مخفی باشد")]
      hidden = 1
    }
    اکنون با کمک product.publishStatus.ToString ستون وضعیت پابلیش را به گرید اضاف میکنم همه چیز به درستی کار میکند اما مشکل این است که:
    در jqgrid هنگام نمایش محتویات این پروپرتی  Show یا hidden را نمایش می‌دهد در صورتی که من می‌خواهم attributes آن یعنی [Display(Name = "نمایش داده شود")]  نمایش داده شود که هر کار میکنم موفق نمیشوم.
    البته می‌توان کلاسی تهیه کرد و در viewmodel یا هنگام mapping این attributes را واکشی کرد ولی نمیدانم راه حل صحیح  آن کدام است و به شیوه ای باید انچام شود.
    آیا هنگام پر کردن RowCells برای json می‌توان به این attributes‌ها دسترسی داشت؟
    ممنون
    • #
      ‫۸ سال و ۷ ماه قبل، شنبه ۲۴ بهمن ۱۳۹۴، ساعت ۱۷:۳۳
      یک متد الحاقی درست کنید تا این اطلاعات اضافی را واکشی کند؛ مانند متد GetDescription  
  • #
    ‫۸ سال و ۴ ماه قبل، دوشنبه ۱۰ خرداد ۱۳۹۵، ساعت ۰۰:۵۳
    با تشکر؛
    یک سوال: آیا درون یک formatter می‌توان به سطر جاری دسترسی داشت؟ 
    فرض کنید یک ستون برای عملیات داریم:
    {
         resize: false, formatter: buttons
    }
    با کمک formatter فوق (button) قرار است یکسری دکمه‌ها نمایش داده شوند:
    function buttons(cellvalue, options, rowObject) {
    var addProjectUrl = $('#getAddProjectUrl').data('url') + "/" + options.rowId;
    
    return "<a href=" + addProjectUrl + ">....
    }
    اکنون باید مقدار ستون قبل از ستون عملیات بررسی شود و نسبت به آن یک لینک دیگر به صورت فوق نمایش داده شود.
  • #
    ‫۷ سال و ۱۰ ماه قبل، دوشنبه ۱۷ آبان ۱۳۹۵، ساعت ۱۴:۱۱
    با سلام
    اطلاعات رو با entity خوندم توی لایه سرویس و با Automapper توی ویومدل بایندکردم و خروجی رو توسط یک اکشن به jqgrid بر میگردونم
    مشکل اینجاست که زمان جستجو به مشکل میخورم
    مثلا دو تا جدول استان و شهر دارم
    که فیلدهاشون Id , Name هستن
    این دوتا جدول رو join می‌کنم و داخل یه ویومدل میریزم با این اسم ها:
    StateId
    StateName
    CityId
    CityName
    چون خاصیت index  توی گریدویو به این شکل هست
     index: ' (StronglyTyped.PropertyName<StateCityViewModel>(x => x.CityName))',
    زمانی که میخوام روی این فیلد جستجو بزنم دچار خطا میشه که میگه این فیلد رو نمیشناسه که راست هم میگه
    ممنون میشم پیشنهادی برای این موضوع بدید
    کد دریافت اطلاعات لایه سرویس هم اینه
    public async Task<DataGridViewModel<StateCityViewModel>> GetDataGridSource(string orderBy, JqGridRequest request, NameValueCollection form, DateTimeType dateTimeType,
                int page, int pageSize)
            {
                var query = _stateCity.AsQueryable();
                
                query = new JqGridSearch(request, form, dateTimeType).ApplyFilter(query);
    
                var resultsToSkip = page * pageSize;
    
                var dataGridModel = new DataGridViewModel<StateCityViewModel>
                {
                    Records = await query.AsQueryable().OrderBy(orderBy)
                        .Skip(() => resultsToSkip)
                        .Take(pageSize).ProjectTo<StateCityViewModel>(null, _mappingEngine).ToListAsync(),
    
                    TotalCount = await query.AsQueryable().OrderBy(orderBy).CountAsync()
                };
    
                return dataGridModel;
            }



    • #
      ‫۷ سال و ۱۰ ماه قبل، دوشنبه ۱۷ آبان ۱۳۹۵، ساعت ۱۵:۱۸
      زمانیکه از AutoMapper استفاده می‌کنید، یک سری «نگاشت» اولیه برای آن لازم هست که مشخص کند، کدام خاصیت مدل باید به کدام خاصیت ویوو مدل متصل شود و همچنین یک سری پیش‌فرض‌هایی هم دارد؛ مانند نگاشت خودکار خواص هم‌نام. در اینجا هم شبیه به همین «نگاشت‌ها» را «خودتان» باید ایجاد کنید. مراجعه کنید به سورس مرتبط و متد getPredicate را اصلاح کنید. اینجا جایی هست که فیلدها به صورت پویا به کوئری اضافه می‌شوند. در این متد فرصت خواهید داشت تا تغییرات مدنظر خودتان را اعمال کنید. مثلا به این کلاس یک دیکشنری اضافه کنید که لیست نگاشت‌ها را دریافت کند. بعد اگر این دیکشنری دارای عضوی بود، در ابتدای متد یاد شده، نام فیلد دریافتی را با فیلد موجود در دیکشنری تعویض کنید.
    • #
      ‫۵ سال و ۱ ماه قبل، چهارشنبه ۹ مرداد ۱۳۹۸، ساعت ۱۶:۲۲
      سلام و ضمن تشکر
      کتابخانه کمکی ارائه شده در لینک برای استفاده در ASP.NET Core را مطالعه کردم و نمونه مثالی که برای دمو در لینک Demo.AspNetCore.JqGrid برای استفاده از این کتابخانه ارائه کرده است را بررسی کردم.
      مشکلی که داشتم با نمونه مثال عنوان شده این کتابخانه در dot NET Core این بود :
      1. قبلا توسط jqGridHelper که شما آن را توسعه داده بودید کوئری‌های جستجو و فیلترینگ داینامیک بر روی جداول اعمال می‌شد و نیاز به  کدنویسی‌های اضافه‌تر سمت سرور برای فیلترینگ هر جدول نبود ولی در این مثالی که برای کتابخانه جدید dot NET Core در لینک ارائه کرده نیاز است تا برای هر جدولی که می‌خواهیم نمایش دهیم چندین متد جداگانه برای فیلتر و مرتب سازی آن سمت سرور پیاده سازی شود ضمن اینکه کوئری جستجو‌ها هم برای هر فیلدی که می‌خواهید در گرید اضافه کنید باید جداگانه سمت سرور کد آن نوشته شود که باعث پیچیده‌تر شدن و کدنویسی بسیار زیاد سمت سرور میشود. 
      2. در کتابخانه jqGridHelper به دلیل نحوه داینامیک بودن و به صورت String بودن کوئری‌های نهایی که به Linq ترجمه می‌شد امکان فعال سازی و استفاده از آن بر روی بانکهای اطلاعاتی NoSQL از قبیل MongoDB با استفاده از MongoDB Driver به راحتی فراهم میشد در حالی که در مثال ارائه شده برای dot Net Core به دلیل ماهیت ساخت داینامیک بودن آن توسط خود Linq و عدم پشتیبانی از این نحو فیلترینگ در درایور دات نتی مونگو امکان استفاده از مثال برای زمانی که از بانک اطلاعاتی مونگو استفاده می‌شود و می‌خواهیم بر روی جداول فیلترینگ انجام دهیم فراهم نمی‌باشد و با خطا مواجه می‌شود

      به همین خاطر سعی کردم تا کدهای کتابخانه jqGridHelper قدیمی که بر روی نسخه قبلی ASP.NET MVC به راحتی برای انواع بانکهای اطلاعاتی از قبیل SQL Server  و MongoDB کار می‌کرد را تغییراتی بدهم تا بتوان از این مثال برای استفاده در dot Net Core در انواع بانکهای اطلاعاتی SQL Server  و  MongoDB و غیره که قبلا استفاده می‌شد به راحتی استفاده کرد و هم کدنویسی سمت سرور برای نمایش و فیلترینگ انواع گرید‌ها را به شدت کاهش می‌دهد
      کتابخانه قبلی jqGridHelper   را همگام با کتابخانه Releasing Lib.AspNetCore.Mvc.JqGrid v1.0.0  تغییر دادم


      دوستان از لینک زیر می‌توانید بهینه سازی شده مثال لینک اول برای استفاده از jqGrid در dotNet Core همراه با قابلیت استفاده با بانک اطلاعاتی Mongo DB را استفاده نمایید.
      Demo-AspNetCore-JqGrid.rar
    • #
      ‫۴ سال و ۹ ماه قبل، چهارشنبه ۲۰ آذر ۱۳۹۸، ساعت ۱۴:۳۹
      سلام
      برای فعال سازی jqGrid در ASP.NET Core 3 به نحوی که بتونه اطلاعات جداول رو نمایش بده توسط متد POST چه تنظیمات دیگری نیازه؟
      تنظیمات ارتقای از ASP.NET2.2 به ASP.NET3.0 رو از این لینک مطالعه کردم و همینطور همه بازخوردهای سایت که در زمینه ارتقای به ASP.NET Core3.0 بود رو مطالعه کردم ولی بازم اطلاعات رو نمایش نمیده؟!
      خطای زیر رو نمایش می‌ده که گویا نتونسته آدرس دهی رو پیدا کنه!

      همینطور بسته‌ی نیوگت Microsoft.AspNetCore.Mvc.NewtonsoftJson را هم برای بخشی که اطلاعات به صورت json به صفحه ارسال میشه نصب کردم ولی اطلاعات رو در جداول نمایش نمیده.
      روی ASP.NET Core 2.2 به خوبی کار می‌کرد ولی با ارتقا به ASP . NET Core 3.0 این مشکل پیش اومده.
      کار خاص دیگرهم باید انجام بدیم؟
      ممنون میشم راهنمایی بفرمایید.

      • #
        ‫۴ سال و ۹ ماه قبل، چهارشنبه ۲۰ آذر ۱۳۹۸، ساعت ۱۴:۵۲
        در برگه‌ی  network، بررسی کنید که دقیقا چه اطلاعاتی با چه فرمتی و خصوصا چه Content-Type ای ارسال شدند. همین موارد را برای response هم بررسی کنید. اگر هدرهای accept و یا Content-Type اشتباه تنظیم شده باشند، ممکن است web api شما خروجی با فرمت xml تولید کند. یا حتی ممکن است خروجی خالی دریافت کرده باشید که به xml تفسیر شده. یا حتی اگر Content-Type خروجی تنظیم نشده باشد، ممکن است این خطای xml parsing error را دریافت کنید (حتی اگر خروجی JSON به نظر برسد).
        • #
          ‫۴ سال و ۹ ماه قبل، چهارشنبه ۲۰ آذر ۱۳۹۸، ساعت ۱۵:۳۹
          با اینکه نوع متدهایی که اطلاعات رو از سرور درخواست میکنه به صورت post تنظیم شده
           <script type="text/javascript">
                  $(function() {
                      $('#jqgStarWarsCharacters').jqGrid({
                          url: '@Url.Action("Characters", "StarWars")',
                          datatype: 'json',
                          mtype: 'POST',
                          cmTemplate: { align: 'center' },
                          colNames: [ 'Name', 'Gender', 'Height', 'Weight', 'Birth Year', 'Skin Color', 'Hair Color', 'Eye Color' ],
                          colModel: [
                                      { name: 'Name' },
                                      { name: 'Gender', sortable: false, formatter: demo.jqGrid.character.genderFormatter },
                                      { name: 'Height', summaryType: 'avg' },
                                      { name: 'Weight', summaryType: 'avg' },
                                      { name: 'BirthYear' },
                                      { name: 'SkinColor', sortable: false, formatter: demo.jqGrid.character.skinColorFormatter },
                                      { name: 'HairColor', sortable: false, formatter: demo.jqGrid.character.hairColorFormatter },
                                      { name: 'EyeColor', sortable: false, formatter: demo.jqGrid.character.eyeColorFormatter }
                                    ],
                          caption: 'StarWars Characters',
                          grouping: true,
                          groupingView: {
                              groupField: ['Gender'],
                              groupDataSorted: true,
                              groupColumnShow: [false],
                              groupSummary: [true]
                          },
                          footerrow: true,
                          userDataOnFooter: true,
                          jsonReader: { repeatitems: false, id: 'Id' },
                          pager: $('#jqgpStarWarsCharacters'),
                          rowNum: 100,
                          sortname: 'Id',
                          sortorder: 'asc',
                          viewrecords: true,
                          height: '100%'
                      });
                  });
              </script>
          ولی توی پوشه Network وقتی دیدم نوعش رو xml نمایش داده. همینطور متد دریافت اطلاعات از سمت سرور اصلا call نمیشه که بخواد پاسخ رو به هرشکلی برگردونه
          کد نوشته شده در بالا در asp.net Core 2.2 درست کار می‌کرد ولی الان در asp.net core 3.0 بخش network این نمایش زیر رو داره
          در این پروژه ارتقا از ASP . NET Core 2.2 به Core 3.0 کلا برای اینکه متدهای Ajax قبلی کار کنه تنظیمات خاص دیگری هم لازمه؟




          توی startup پروژه هم با ارتقا به Core 3.0 متدها به صورت زیر نوشته شده که متد UseMVC قبلی رو حذف کردم

          public void ConfigureServices(IServiceCollection services)
                  {
                      services.AddControllersWithViews();
                      services.AddRazorPages();
                      services.AddControllers()
                          .AddNewtonsoftJson();
                  }
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
                  {
                      if (env.IsDevelopment())
                      {
                          app.UseDeveloperExceptionPage();
                      }
          
                      app.UseHttpsRedirection();
                      app.UseStaticFiles();
           JqGridRequest.ParametersNames = new JqGridParametersNames() { PagesCount = "npage" }; app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); endpoints.MapControllerRoute( name: "default", pattern: "{controller=JavaScript}/{action=Basics}"); endpoints.MapControllerRoute( name: "default2", pattern: "{controller=StarWars}/{action=Characters}/{id?}"); endpoints.MapRazorPages(); }); }



          • #
            ‫۴ سال و ۹ ماه قبل، چهارشنبه ۲۰ آذر ۱۳۹۸، ساعت ۱۵:۵۳
            این تنظیمات را برای تغییر content-type مربوط به jqGrid آزمایش کنید:
            - برای یک گرید:
            $("#contactsList").jqGrid({
                            mtype: 'POST',
                            ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
            - به صورت سراسری:
            $.extend($.jgrid.defaults, {
                datatype: 'json',
                ajaxGridOptions: { contentType: "application/json" },
                ajaxRowOptions: { contentType: "application/json", type: "PUT" },
                ajaxSelectOptions: { contentType: "application/json", dataType: "JSON" }
            });
            
            $.extend($.jgrid.edit, {
                ajaxEditOptions: { contentType: "application/json" },
                recreateForm: true,
                serializeEditData: function(postData) {
                    return JSON.stringify(postData);
                }
            });
            
            $.extend($.jgrid.del, {
                ajaxDelOptions: { contentType: "application/json" },
                mtype: "DELETE"
            });
            • #
              ‫۴ سال و ۹ ماه قبل، چهارشنبه ۲۰ آذر ۱۳۹۸، ساعت ۱۷:۴۹
              همه اون مواردی هم که اشاره فرمودید انجام دادم، ولی بازم خطا می‌ده و اطلاعات رو داخل گرید‌ها نمایش نمی‌ده:

              • #
                ‫۴ سال و ۹ ماه قبل، چهارشنبه ۲۰ آذر ۱۳۹۸، ساعت ۱۸:۳۷
                برگه Response را مرور کنید، خطای سمت سرور رخ داده! متن خطا در برگه Response نمایش داده،
                جهت ارتقاء به ASP.NET CORE 3 این قسمت را مرور کنید:
                همچنین این قسمت:
                • #
                  ‫۴ سال و ۸ ماه قبل، یکشنبه ۲۴ آذر ۱۳۹۸، ساعت ۱۴:۲۲
                  این موارد رو با اینکه قبلا مطالعه کرده بودم دوباره دقیق‌تر مطالعه کردم
                  ولی مشکلی که وجود داره اینه که با وجود اینکه Routing‌ها به همین شکلی که توی ASP.NET Core 3.0 گفته شده رو تنظیم کردم
                    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
                          { 
                              if (env.IsDevelopment())
                              {
                                  app.UseDeveloperExceptionPage();
                              }
                  
                              app.UseHttpsRedirection();
                              app.UseStaticFiles();
                  
                              JqGridRequest.ParametersNames = new JqGridParametersNames() {  PagesCount = "npage" };
                              app.UseRouting();
                              app.UseAuthorization();
                  
                              app.UseEndpoints(endpoints =>
                              { 
                                  endpoints.MapControllerRoute(
                                      name: "default",
                                      pattern: "{controller=JavaScript}/{action=Basics}/{id?}");
                  
                                  endpoints.MapControllerRoute(
                                     name: "default2",
                                     pattern: "{controller=StarWars}/{action=Characters}");
                           
                                  endpoints.MapRazorPages(); 
                              });
                          }


                  ولی متد سمت سرور اصلا Call نمیشه که بخواد جواب رو نمایش بده
                  شاید لازم باشه object از کلاس JqGridRequest که ورودی متد Characters هست خصوصیات کلاسش تغییراتی بر حسب System.Text.Json داشته باشه تا بتونه متد سمت سرور رو صحیح Call کنه
                  یعنی تبدیل رشته‌ی JSON به شیء متناظر با آن و یا حالت عکس آن گویا به صورت صحیح انجام نمیشه احتمالا باید پروژه Lib.AspNetCore.Mvc.JqGrid  بر حسب ASP.NET Core 3.0 کامپایل بشه


                  در اینجاهم یه کامنت در مورد تغییرات JSON serialization/deserialization گذاشتند
                  • #
                    ‫۴ سال و ۸ ماه قبل، یکشنبه ۲۴ آذر ۱۳۹۸، ساعت ۱۴:۵۹
                    - زمانیکه خطای 500 internal server error را دریافت می‌کنید، اگر برنامه را در حالت dotnet run اجرا کرده باشید، تمام خطاهای مرتبط، در پنجره‌ی کنسولی که باز است، لاگ می‌شوند. اگر از ویژوال استودیو استفاده می‌کنید، همین خروجی، در پنجره‌ی دیباگ آن هم درج می‌شود. مرور این خطاهای سمت سرور، برای رفع مشکل الزامی است.
                    - همچنین احتمال دارد خروجی خطاهای سمت سرور، در قسمت مشاهده‌ی محتوای response، در برگه‌ی ابزارهای توسعه دهندگان مرورگر هم ظاهر شود. آن‌را هم بررسی کنید.
                    • #
                      ‫۴ سال و ۸ ماه قبل، یکشنبه ۲۴ آذر ۱۳۹۸، ساعت ۱۷:۱۱
                      خطای زیر رو ایجاد کرده در کلاس داخلی JqGridRequestModelBinder مربوط به کتابخانه Lib.AspNetCore.Mvc.JqGrid
                      برای همین چون نمی‌تواند Binding مدل را به درستی انجام دهد exception داخلی ایجاد می‌کرده و مدل سازی ورودی متد به درستی انجام نمیشده.
                      به نظرتون برای رفع این مشکل راه حلی هست؟ یا باید منتظر باشیم تا نسخه‌های بعدی ASP.NET Core ؟

                      Could not load type 'Microsoft.AspNetCore.Mvc.ModelBinding.Internal.ModelBindingHelper' 
                      from assembly 'Microsoft.AspNetCore.Mvc.Core, Version=3.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.

                      • #
                        ‫۴ سال و ۸ ماه قبل، یکشنبه ۲۴ آذر ۱۳۹۸، ساعت ۱۸:۳۲
                        Type Load Exception فقط به معنای binary-mismatch است. یعنی کتابخانه‌ی مدنظر شما از وابستگی‌های قدیمی استفاده می‌کند که با نگارش ASP.NET Core مورد استفاده‌ی در پروژه‌ی شما یکی نیست. فقط یک راه حل هم دارد: به روز رسانی وابستگی‌های کتابخانه و کامپایل مجدد آن.
                        • #
                          ‫۴ سال و ۸ ماه قبل، یکشنبه ۲۴ آذر ۱۳۹۸، ساعت ۲۲:۵۹
                          سلام و ممنون از راهنمایی‌های خوبتان
                          کتابخانه اصلی Lib.AspNetCore.Mvc.JqGrid مربوط به پروژه Demo.AspNetCore.JqGrid رو با نسخه ASP.NET Core 3.1 به روز رسانی کردم و بعضی خطاهای Type Load Exception هم که در سورس فریمورک اصلی بود برطرف کردم. چون کدهای سورس اصلی فریمورک پروژه رو مجبور شدم تغییر بدم دیگه نشد که به صورت nuget Package به پروژه اضافه کنم برای همین سورس فریمورک اصلی رو در یک پوشه در کنار پروژه دمو که همه را به نسخه ASP.NET Core 3.1 به روز رسانی کردم گذاشتم. البته این نسخه با همان شیوه ای هست که در این لینک توضیح داده بودم و هم میشه با انواع بانکهای اطلاعاتی NoSQL استفاده کرد و هم با بانک اطلاعاتی‌های رابطه ای از قبیل MS SQL Server.

                          ضمنا اون موارد خطا هم به خاطر همین exception داخلی Type Load Exception در فریمورک اصلی بود که پس از ارتقا به نسخه 3.1 برطرف شد.


                          دوستان از لینک زیر می‌توانید نسخه بروز رسانی شده با ASP.NET Core 3.1 را استفاده نمایید.
                          Demo.JqGrid.core3.1.rar  (6.25 MB) 




                          در لینک هم همون نسخه دمو به همراه سورسهای فریمورک اصلی رو که تغییر دادم برای نویسنده اصلی فریمورک Lib.AspNetCore.Mvc.JqGrid در کامنت بارگزاری کردم تا فریمورک اصلی رو هم بروز رسانی کنند تا بعدا بشه به صورت nuget package استفاده کرد. البته توی اون نسخه کتابخانه JqGrid.Core که در نمونه مثال اینجا آپلود کردم نیست به این دلیل که نمونه مثال خودشون رو داشته باشند و باعث پیچیدگی کد برای ارتقای package نشه


                          سورس پروژه رو با این تغییرات در گیتهاب هم منتشر کردم