ASP.NET MVC 2.0 jqgrid中搜索的实现

Posted

技术标签:

【中文标题】ASP.NET MVC 2.0 jqgrid中搜索的实现【英文标题】:ASP.NET MVC 2.0 Implementation of searching in jqgrid 【发布时间】:2011-07-26 22:15:13 【问题描述】:

您好,我正在尝试使用 MVC 2 IN .NET (VS 2008) 在 jqgrid 中使用单列搜索,这是我目前拥有的代码,但我需要一个示例来匹配它或我所缺少的提示

jQuery("#list").jqGrid(
    url: '/Home/DynamicGridData/',
    datatype: 'json',
    mtype: 'POST',
    search: true,
    filters: 
        "groupOp":"AND",
        "rules": [
            "field":"Message","op":"eq","data":"True"
        ]
    ,
    multipleSearch: false,
    colNames: [ 'column1', 'column2'],
    colModel: [
         name: 'column1', index: 'column1', sortable: true, search: true,
          sorttype: 'text', autoFit: true,stype:'text',
          searchoptions:  sopt: ['eq', 'ne', 'cn'] ,
         name: 'column2', index: 'column2', sortable: true,search: false,
          sorttype: 'text', align: 'left', autoFit: true],
    pager: jQuery('#pager'),
    rowNum: 10,
    rowList: [10, 60, 100],
    scroll: true,
    sortname: 'column2',
    sortorder: 'asc',
    gridview: true,
    autowidth: true,
    rownumbers: true,
    viewrecords: true,
    imgpath: '/scripts/themes/basic/images',
    caption: 'my data grid'
);

jQuery("#list").jqGrid('navGrid', '#pager', add: false, edit: false, del: false,
                       , , ,  multipleSearch: true, overlay: false );
//jQuery("#list").jqGrid('filterToolbar', stringResult:true, searchOnEnter:true);
jQuery("#list").jqGrid('navButtonAdd', '#pager',
                       caption: "Finding", title: "Toggle Search Bar",
                        buttonicon: 'ui-icon-pin-s',
                        onClickButton: function()  $("#list")[0].toggleToolbar() 
                      );

jQuery("#list").jqGrid = 
    search : 
        caption: "Search...",
        Find: "Find",
        Reset: "Reset",
        odata : ['equal', 'not equal','contains'],
        groupOps: [  op: "AND", text: "all" ,  op: "OR", text: "any"  ],
        matchText: " match",
        rulesText: " rules"
    
                              

);

两件事分页没有出现 和搜索虽然我打开搜索窗口时只使用 hte column1 作为选项,当单击查找时,它似乎加载了网格,但实际上与我在文本框中键入的值不匹配。

更新:如您所见,我尝试使用 serach 参数但未成功再次感谢您的帮助,不胜感激

//public ActionResult DynamicGridData(string sidx, string sord, int page, int rows,bool search, string fieldname,string fieldvalue)
public ActionResult DynamicGridData(string sidx, string sord, int page, int rows)

    var context = new  AlertsManagementDataContext();
    int pageIndex = Convert.ToInt32(page) - 1;
    int pageSize = rows;
    int totalRecords = context.Alerts.Count();
    int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);

    IQueryable<Alert> alerts = null;
    try
    
       //if (!search)
       //
           alerts = context.Alerts.
           OrderBy(sidx + " " + sord).
           Skip(pageIndex * pageSize).
           Take(pageSize);
       //
       //else
       //
       //    alerts = context.Alerts.Where (fieldname +"='"+ fieldvalue +"'").
       //    Skip(pageIndex * pageSize).
       //    Take(pageSize);
       //
    
    catch (ParseException ex)
    
        Response.Write(ex.Position + "  " + ex.Message + "  " + ex.Data.ToString());
    

    //var alerts =
    //    from a in context.Alerts
    //    orderby sidx ascending
    //    select a;

    var jsonData = new 
        total = totalPages,
        page = page,
        records = totalRecords,

        rows = (
          from alert in alerts

          select new 
            id = alert.AlertId,
            cell = new string[] 
                "<a href=Home/Edit/"+alert.AlertId +">Edit</a> " +"|"+
                    "<a href=Home/Details/"+alert.AlertId +">Detail</a> ",
                alert.AlertId.ToString() ,
                alert.Policy.Name ,
                alert.PolicyRule ,
                alert.AlertStatus.Status ,
                alert.Code.ToString() ,
                alert.Message ,
                alert.Category.Name
        ).ToArray()
    ;

    return Json(jsonData);

【问题讨论】:

我修改了问题的标题和标签以包含有关 ASP.NET MVC 的信息。您可以自己再更正一次文本。 【参考方案1】:

可能您在服务器端有问题。您能否将您的问题附加到您当前使用的 DynamicGridData 操作代码中。该操作应以filters 作为参数。

您当前代码的某些部分肯定是错误的。例如jqGrid 是 jQuery 插件。因此,jQuery 的方法将使用您用作jQuery("#list").jqGrid(...); 的主要jqGrid 方法进行扩展。所以在jqGrid初始化之后jQuery("#list").jqGrid会是一个函数。在您的代码(最后一条语句)中,您用对象 search: ... 覆盖jQuery("#list").jqGrid 方法。你应该做的是

jQuery.extend(jQuery.jgrid.search, 
    odata : ['equal', 'not equal','contains']
);

例如here 描述了如何覆盖emptyrecords 默认值。您不需要在默认 jqGrid 设置中包含已经相同的值。

此外,如果您在所有可搜索列上使用 searchoptions: sopt: ['eq', 'ne', 'cn'],则无需进行更改。

在您的问题文本中,您没有解释您想要做什么。您当前的代码是让您在初始网格加载时使用等于true 的过滤器Message。奇怪的是网格中没有名称为Message 的列。如果您只想向服务器发送一些附加信息,您最好使用postData 参数:

postData: Message:true

我继续建议您从 jqGrid 定义中删除垃圾,例如 jqGrid 和 sortable: true, search: true, sorttype: 'text', autoFit: true, stype:'text', align: 'left'imgpathmultipleSearch 参数,它们是未知的或默认的。

更新:the Phil Haack demo 的原始代码很老,它使用 LINQ to SQL。就像我之前写的(参见here)实体框架(EF)允许使用排序、分页和过滤/搜索,而无需任何附加组件,如System.Linq.Dynamic 形式的LINQ 动态查询库。所以我给你做了一个演示,将the Phil Haack demo修改为EF。

因为你使用的是旧版本的 Visual Studio(VS2008 和 ASP.NET MVC 2.0)我也在 VS2008 中做了演示。

你可以从here和VS2010演示here下载我的VS2008演示。

在我展示的代码中(除了在 ASP.NET MVC 2.0 中使用高级搜索和工具栏搜索)如何以 JSON 格式从 ASP.NET MVC 返回异常信息以及如何使用loadError 捕获信息方法并显示相应的错误信息。

为了从 ObjectQuery 表示的 EF 对象构造 Where 语句,我定义了以下帮助程序类:

public class Filters 
    public enum GroupOp 
        AND,
        OR
    
    public enum Operations 
        eq, // "equal"
        ne, // "not equal"
        lt, // "less"
        le, // "less or equal"
        gt, // "greater"
        ge, // "greater or equal"
        bw, // "begins with"
        bn, // "does not begin with"
        //in, // "in"
        //ni, // "not in"
        ew, // "ends with"
        en, // "does not end with"
        cn, // "contains"
        nc  // "does not contain"
    
    public class Rule 
        public string field  get; set; 
        public Operations op  get; set; 
        public string data  get; set; 
    

    public GroupOp groupOp  get; set; 
    public List<Rule> rules  get; set; 
    private static readonly string[] FormatMapping = 
        "(it.0 = @p1)",                 // "eq" - equal
        "(it.0 <> @p1)",                // "ne" - not equal
        "(it.0 < @p1)",                 // "lt" - less than
        "(it.0 <= @p1)",                // "le" - less than or equal to
        "(it.0 > @p1)",                 // "gt" - greater than
        "(it.0 >= @p1)",                // "ge" - greater than or equal to
        "(it.0 LIKE (@p1+'%'))",        // "bw" - begins with
        "(it.0 NOT LIKE (@p1+'%'))",    // "bn" - does not begin with
        "(it.0 LIKE ('%'+@p1))",        // "ew" - ends with
        "(it.0 NOT LIKE ('%'+@p1))",    // "en" - does not end with
        "(it.0 LIKE ('%'+@p1+'%'))",    // "cn" - contains
        "(it.0 NOT LIKE ('%'+@p1+'%'))" //" nc" - does not contain
    ;
    internal ObjectQuery<T> FilterObjectSet<T> (ObjectQuery<T> inputQuery) where T : class 
        if (rules.Count <= 0)
            return inputQuery;

        var sb = new StringBuilder();
        var objParams = new List<ObjectParameter>(rules.Count);

        foreach (Rule rule in rules) 
            PropertyInfo propertyInfo = typeof (T).GetProperty (rule.field);
            if (propertyInfo == null)
                continue; // skip wrong entries

            if (sb.Length != 0)
                sb.Append(groupOp);

            var iParam = objParams.Count;
            sb.AppendFormat(FormatMapping[(int)rule.op], rule.field, iParam);

            // TODO: Extend to other data types
            objParams.Add(String.Compare(propertyInfo.PropertyType.FullName,
                                         "System.Int32", StringComparison.Ordinal) == 0
                              ? new ObjectParameter("p" + iParam, Int32.Parse(rule.data))
                              : new ObjectParameter("p" + iParam, rule.data));
        

        ObjectQuery<T> filteredQuery = inputQuery.Where (sb.ToString ());
        foreach (var objParam in objParams)
            filteredQuery.Parameters.Add (objParam);

        return filteredQuery;
    

在示例中,我仅使用两种数据类型 integer (Edm.Int32) 和 string (Edm.String)。您可以根据propertyInfo.PropertyType.FullName 值轻松扩展示例以使用更多类型。

向 jqGrid 提供数据的控制器操作非常简单:

public JsonResult DynamicGridData(string sidx, string sord, int page, int rows, bool _search, string filters)


    var context = new HaackOverflowEntities();
    var serializer = new javascriptSerializer();
    Filters f = (!_search || string.IsNullOrEmpty (filters)) ? null : serializer.Deserialize<Filters> (filters);
    ObjectQuery<Question> filteredQuery =
        (f == null ? context.Questions : f.FilterObjectSet (context.Questions));
    filteredQuery.MergeOption = MergeOption.NoTracking; // we don't want to update the data
    var totalRecords = filteredQuery.Count();

    var pagedQuery = filteredQuery.Skip ("it." + sidx + " " + sord, "@skip",
                                        new ObjectParameter ("skip", (page - 1) * rows))
                                 .Top ("@limit", new ObjectParameter ("limit", rows));
    // to be able to use ToString() below which is NOT exist in the LINQ to Entity
    var queryDetails = (from item in pagedQuery
                        select new  item.Id, item.Votes, item.Title ).ToList();

    return Json(new 
                    total = (totalRecords + rows - 1) / rows,
                    page,
                    records = totalRecords,
                    rows = (from item in queryDetails
                            select new[] 
                                item.Id.ToString(),
                                item.Votes.ToString(),
                                item.Title
                            ).ToList()
                );

为了以 JSON 形式将异常信息发送到 jqGrid,我将控制器的标准 [HandleError] 属性 (HomeController) 替换为 [HandleJsonException],我将其定义如下:

// to send exceptions as json we define [HandleJsonException] attribute
public class ExceptionInformation 
    public string Message  get; set; 
    public string Source  get; set; 
    public string StackTrace  get; set; 

public class HandleJsonExceptionAttribute : ActionFilterAttribute 
    // next class example are modification of the example from
    // the http://www.dotnetcurry.com/ShowArticle.aspx?ID=496
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
        if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null) 
            filterContext.HttpContext.Response.StatusCode =
                (int)System.Net.HttpStatusCode.InternalServerError;

            var exInfo = new List<ExceptionInformation>();
            for (Exception ex = filterContext.Exception; ex != null; ex = ex.InnerException) 
                PropertyInfo propertyInfo = ex.GetType().GetProperty ("ErrorCode");
                exInfo.Add(new ExceptionInformation() 
                    Message = ex.Message,
                    Source = ex.Source,
                    StackTrace = ex.StackTrace
                );
            
            filterContext.Result = new JsonResult() Data=exInfo;
            filterContext.ExceptionHandled = true;
        
    

在客户端,我使用了以下 JavaScript 代码:

var myGrid = $('#list'),
    decodeErrorMessage = function(jqXHR, textStatus, errorThrown) 
        var html, errorInfo, i, errorText = textStatus + '\n' + errorThrown;
        if (jqXHR.responseText.charAt(0) === '[') 
            try 
                errorInfo = $.parseJSON(jqXHR.responseText);
                errorText = "";
                for (i=0; i<errorInfo.length; i++) 
                   if (errorText.length !== 0) 
                       errorText += "<hr/>";
                   
                   errorText += errorInfo[i].Source + ": " + errorInfo[i].Message;
                
            
            catch (e)  
         else 
            html = /<body.*?>([\s\S]*)<\/body>/.exec(jqXHR.responseText);
            if (html !== null && html.length > 1) 
                errorText = html[1];
            
        
        return errorText;
    ;
myGrid.jqGrid(
    url: '<%= Url.Action("DynamicGridData") %>',
    datatype: 'json',
    mtype: 'POST',
    colNames: ['Id', 'Votes', 'Title'],
    colModel: [
         name: 'Id', index: 'Id', key: true, width: 40,
            searchoptions:  sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge'] 
        ,
         name: 'Votes', index: 'Votes', width: 40,
            searchoptions:  sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge'] 
        ,
         name: 'Title', index: 'Title', width: 400,
            searchoptions:  sopt: ['cn', 'nc', 'bw', 'bn', 'eq', 'ne', 'ew', 'en', 'lt', 'le', 'gt', 'ge'] 
        
    ],
    pager: '#pager',
    rowNum: 10,
    rowList: [5, 10, 20, 50],
    sortname: 'Id',
    sortorder: 'desc',
    rownumbers: true,
    viewrecords: true,
    altRows: true,
    altclass: 'myAltRowClass',
    height: '100%',
    jsonReader:  cell: "" ,
    caption: 'My first grid',
    loadError: function(jqXHR, textStatus, errorThrown) 
        // remove error div if exist
        $('#' + this.id + '_err').remove();
        // insert div with the error description before the grid
        myGrid.closest('div.ui-jqgrid').before(
            '<div id="' + this.id + '_err" style="max-width:'+this.style.width+
            ';"><div class="ui-state-error ui-corner-all" style="padding:0.7em;float:left;"><span class="ui-icon ui-icon-alert" style="float:left; margin-right: .3em;"></span><span style="clear:left">' +
                        decodeErrorMessage(jqXHR, textStatus, errorThrown) + '</span></div><div style="clear:left"/></div>')
    ,
    loadComplete: function() 
        // remove error div if exist
        $('#' + this.id + '_err').remove();
    
);
myGrid.jqGrid('navGrid', '#pager',  add: false, edit: false, del: false ,
              , , ,  multipleSearch: true, overlay: false );
myGrid.jqGrid('filterToolbar',  stringResult: true, searchOnEnter: true, defaultSearch: 'cn' );
myGrid.jqGrid('navButtonAdd', '#pager',
             caption: "Filter", title: "Toggle Searching Toolbar",
                buttonicon: 'ui-icon-pin-s',
                onClickButton: function()  myGrid[0].toggleToolbar(); 
            );

结果,如果在搜索工具栏中键入任何非数字文本(如“ttt”),则会收到控制器操作代码异常(在Int32.Parse(rule.data) 中)。客户端之一将看到以下消息:

我从控制器向 jqgrid 发送有关所有内部异常的信息。因此,例如,连接到 SQL 服务器的错误看起来像

在现实世界中,验证用户输入并使用面向应用程序的错误消息引发异常。我在demo中特别使用了没有这样的验证来显示所有类型的异常都会被jqGrid缓存和显示。

更新 2:在 the answer 中,您将找到修改后的 VS2010 演示(可从 here 下载),它演示了 jQuery UI 自动完成的用法。 Another answer 进一步扩展代码以导出 Excel 格式的网格。

【讨论】:

@Sue:首先,我将您发布的代码从问题的答案中移出。您对示例使用一些常见的数据库还是自己的?我现在很忙,但稍后我会尝试更正您的代码。 LINQ to SQL 的使用对您来说很重要还是实体框架 (EF) 数据库访问非常有趣?我问是因为在 EF 中更容易创建仅基于文本输入字符串的动态查询,就像在 jqGrid 的情况下一样。 @Sue: 如果你去掉multipleSearch:true搜索选项,那么搜索对话框将在请求中发送_searchsearchFieldsearchStringsearchOper(大小写很重要)参数到服务器。如果没有multipleSearch:true,搜索工具栏的格式将是其他格式:发送到服务器的参数将类似于列名(column2 或/和column2)。因此,主要使用multipleSearch:true,并在服务器方法中将filters 参数转换为JavaScriptSerializerDataContractJsonSerializer 的对象。 @Sue:我的主要想法是在实体框架的情况下使用ObjectQuery&lt;T&gt; 比使用IQueryable&lt;T&gt; 更好,因为IQueryable&lt;T&gt; 不支持您作为输入接收的字符串参数jq网格。如果您使用IQueryable&lt;T&gt;,则必须在您的项目中包含System.Linq.Dynamic.dll 或像tpeczek 这样的LINQ 动态查询库的源代码(它有4000 多行代码)。在使用实体框架的情况下,ObjectQuery&lt;T&gt; 的使用更有效。这是我的主要声明。 @Learning:上面的代码就是这样做的。参见DynamicGridData 的代码。您可以删除部分代码。如果您是初学者,我建议您准确考虑是否真的需要 服务器端 分页。客户端分页/排序/过滤对大约 1000 行的工作速度足够快。尝试使用 4000 和 40000 行的 the demo 和 this one @Learning:请更准确地写出您需要的内容。 ASP.NET MVC 仍然是 ASP.NET。您询问了“在 asp.net 中”的示例。你到底是什么技术?例如,another answer 提供了一个使用 ASHX 的示例(IHttpHandlerProcessRequestIsReusable)。可能这就是您要找的东西?【参考方案2】:

查看以下链接:

jqGrid and ASP.NET MVC - Searching <-- ASP.NET MVC LinqToSql jqGrid in ASP.NET MVC 3 and Razor <-- lot of samples, ASP.NET MVC 3, Razor jqGrid in ASP.NET MVC - Strongly typed helper <-- same samples as above but with strongly typed helper and Entity Framework Code-First

【讨论】:

我发现提供使用 jqGrid 的 ASP.NET MVC 示例的想法非常好,但是您当前实现的某些部分有点脏。例如,您应该包含loadError(请参阅我的示例中的[HandleJsonException] 属性和decodeErrorMessage)。从搜索方面来看,您的所有示例仅支持两种操作:'eq' 和'ne'。至少应该包括“cn”或“bw”操作。旧的“MVC - 搜索”中的手动 JSON 反序列化我发现了错误的方法。抱歉这么多批评点,但您的示例显示了更多 MVC 作为 jqGrid 最佳实践。 其他一些小东西,例如&lt;style type="text/css"&gt;/* fix the size of the pager */input.ui-pg-input width: auto; &lt;/style&gt; 或使用height:'100%' 而不是height:'auto'(由于IE9 错误)可以改进您的示例。 jqGrid 不支持width:'auto' 的使用。 '#jqgpProducts' 的用法不如$('#jqgpProducts') 好。不应该包含默认属性,如align:'left'search: truestype: 'text' 等等。我只想在 jqGrid 的最佳实践下进一步解释我的意思。 还有一个建议:如果您修改 MVC 项目的默认 Site.css 或在 @ 之后的 _Layout.cshtml 中包含 &lt;style type="text/css"&gt; table border-style:none; border-collapse:separate; table td border-style:none; &lt;/style&gt;,则可以从示例的 jqGrids 中删除水平滚动条987654339@,其中包括site.css @Oleg 每一个建设性的批评点都是一个很好的批评点:)。我将在下一次迭代中考虑您的所有建议。其中一些实际上已经被更改(例如强类型帮助程序生成 pager: '#0Pager' 而不是 pager: $('#0Pager'))。如果您有更多建议,请随时告诉我 - 特别是如果他们考虑使用强类型帮助器(您甚至可以在 CodePlex 上给我一个问题),因为我真的想让它成为一个可用的软件。跨度> 好的!我会再仔细看一遍代码,并将我的建议发布到 CodePlex 上。【参考方案3】:

我尝试使用搜索参数但未成功

public ActionResult DynamicGridData(string sidx, string sord, int page, int rows)

  var context = new  AlertsManagementDataContext();
  int pageIndex = Convert.ToInt32(page) - 1;
  int pageSize = rows;
  int totalRecords = context.Alerts.Count();
  int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
  IQueryable<Alert> alerts = null;
  try
  
      //if (!search)
      //   
      alerts = context.Alerts.
      OrderBy(sidx + " " + sord).
      Skip(pageIndex * pageSize).
      Take(pageSize);
      //     
      //else
      //    
      //        alerts = context.Alerts.Where (fieldname +"='"+ fieldvalue +"'").
      //         Skip(pageIndex * pageSize).
      //         Take(pageSize);
      //    
      
   catch (ParseException ex)
  
     Response.Write(ex.Position + "  " + ex.Message + "  " + ex.Data.ToString());
  
//var alerts =
//    from a in context.Alerts
//    orderby sidx ascending
//    select a;
   var jsonData = new 
                     total = totalPages,
                     page = page,
                     records = totalRecords,
   rows = ( from alert in alerts                            
                select new 
                            id = alert.AlertId,
                            cell = new string[]  
                                "<a href=Home/Edit/"+alert.AlertId +">Edit</a> " +"|"+ "<a href=Home/Details/"+alert.AlertId +">Detail</a> ",
                                alert.AlertId.ToString() , 
                                alert.Policy.Name , 
                                alert.PolicyRule , 
                                alert.AlertStatus.Status , 
                                alert.Code.ToString() , 
                                alert.Message , 
                                alert.Category.Name
                        ).ToArray()
                  ;

返回 Json(jsonData);

【讨论】:

【参考方案4】:

服务器端搜索比您想象的要容易得多。 网格中的索引将在 json 调用中作为参数出现。 如果是搜索,GridSettings 参数中还有一个参数将设置为 true。它称为 IsSearch。 GridSettings 参数中还有一个排序顺序和列,可以帮助您构建 dy

所以,你会有这样的东西..

public JsonResult GetUsers(GridSettings gridSettings, string FirstName, string LastName)
  
    // conditional logic and queries here and return results)

【讨论】:

以上是关于ASP.NET MVC 2.0 jqgrid中搜索的实现的主要内容,如果未能解决你的问题,请参考以下文章

ASP.net MVC 代码片段问题中的 Jqgrid 实现

datetimepicker jqgrid asp.net mvc

如何使用asp.net mvc删除jqgrid中的多个寄存器?

jqGrid postdata 发送空值(mvc3 asp/net)

无法在 asp.net mvc 4 中将 JSON 对象映射到 JqGrid

ASP.NET MVC+EF在服务端分页使用jqGrid以及jquery Datatables的注意事项