ASP.NET MVC 2.0 在jqgrid中搜索的实现 [英] ASP.NET MVC 2.0 Implementation of searching in jqgrid

查看:31
本文介绍了ASP.NET MVC 2.0 在jqgrid中搜索的实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Hi I am trying to use the single column search in jqgrid using MVC 2 IN .NET (VS 2008) this is the code I have so far but I need an example to match it with or a tip of what I am missing

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 作为选项,当单击查找时,它似乎加载了网格,但实际上与我在文本框中键入的值不匹配.

two things paging is not coming up and search although I have the search window opening with just hte column1 as an option and when clicking the find it seems like it loads the grid but actually without matching my value that I type in the text box.

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

UPDATED: as you can see I made an attempt with the serach argument that did not succeed thanks again for your help it is appreciated

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

推荐答案

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

Probably you have problem on the server side. Could you append your question with the code of DynamicGridData action which you currently use. The action should have filters as the parameter.

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

Some parts of your current code are definitively wrong. For example jqGrid is the jQuery plugin. So the methods of jQuery will be extended with the main jqGrid method which you use as jQuery("#list").jqGrid(...);. So after the initializing of jqGrid jQuery("#list").jqGrid will be a function. In you code (the last statement) you overwrite the jQuery("#list").jqGrid method with the object { search: { ... } }. What you should do instead is

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

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

like for example here is described how to overwrite the emptyrecords default value. You don't need to include the values which are already the same in the default jqGrid settings.

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

Moreover if you use searchoptions: { sopt: ['eq', 'ne', 'cn']} on all searchable columns you don't need to do the change.

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

In the text of your question you don't explained what you want to do. Your current code is so that you use the filter Message equal to true at the initial grid loading. Strange is that there are no column with the name Message in the grid. If you want just send some additional information to the server you should better use postData parameter:

postData: {Message:true}

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

I continue to recommend you to remove garbage from the jqGrid definition like imgpath and multipleSearch parameters of jqGrid and sortable: true, search: true, sorttype: 'text', autoFit: true, stype:'text', align: 'left' which are either unknown or default.

更新:Phil Haack 演示 非常古老,它使用 LINQ to SQL.就像我之前写的(见这里)实体框架(EF)允许使用排序、分页和过滤/搜索,无需任何附加组件,例如 System.Linq.Dynamic 形式的 LINQ 动态查询库.所以我做了你的演示,这是对 Phil Haack 演示到 EF.

UPDATED: The original code of the Phil Haack demo is very old and it use LINQ to SQL. Like I wrote before (see here) Entity Framework (EF) allows to use sorting, paging and filtering/searching without any AddOns like LINQ Dynamic Query Library in form System.Linq.Dynamic. So I made the demo you you which is modification of the the Phil Haack demo to EF.

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

Because you use the old version of Visual Studio (VS2008 with ASP.NET MVC 2.0) I made the demo also in VS2008.

您可以从 此处 和 VS2010 演示下载我的 VS2008 演示此处.

You can download my VS2008 demo from here and VS2010 demo here.

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

In the code I show (additionally to the usage of Advanced Searching and Toolbar Searching in ASP.NET MVC 2.0) how to return exception information from ASP.NET MVC in JSON format and how to catch the information with the loadError method and display the corresponding error message.

ObjectQuery 表示 EF 对象我定义了以下帮助类:

To construct the Where statement from the ObjectQuery represented EF object I define the following helper class:

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} = @p{1})",                 // "eq" - equal
        "(it.{0} <> @p{1})",                // "ne" - not equal
        "(it.{0} < @p{1})",                 // "lt" - less than
        "(it.{0} <= @p{1})",                // "le" - less than or equal to
        "(it.{0} > @p{1})",                 // "gt" - greater than
        "(it.{0} >= @p{1})",                // "ge" - greater than or equal to
        "(it.{0} LIKE (@p{1}+'%'))",        // "bw" - begins with
        "(it.{0} NOT LIKE (@p{1}+'%'))",    // "bn" - does not begin with
        "(it.{0} LIKE ('%'+@p{1}))",        // "ew" - ends with
        "(it.{0} NOT LIKE ('%'+@p{1}))",    // "en" - does not end with
        "(it.{0} LIKE ('%'+@p{1}+'%'))",    // "cn" - contains
        "(it.{0} NOT LIKE ('%'+@p{1}+'%'))" //" 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 值轻松扩展示例以使用更多类型.

In the example I use only two datatypes integer (Edm.Int32) and string (Edm.String). You can easy expand the example to use more types based as above on the propertyInfo.PropertyType.FullName value.

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

The controller action which provide the data to the jqGrid will be pretty simple:

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,我将控制器 (HomeController) 的标准 [HandleError] 属性替换为 [HandleJsonException] 我定义如下:

To send the exception information to the jqGrid in JSON form I replaced the standard [HandleError] attribute of the controller (HomeController) to the [HandleJsonException] which I defined as the following:

// 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 代码:

On the client side I used the following JavaScript code:

var myGrid = $('#list'),
    decodeErrorMessage = function(jqXHR, textStatus, errorThrown) {
        var html, errorInfo, i, errorText = textStatus + '
' + 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.*?>([sS]*)</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) 中).一个客户端会看到以下消息:

As the result if one types any non-numeric text (like 'ttt') in the searching toolbar one receive exception the controller action code (in Int32.Parse(rule.data)). One the client side one will see the following message:

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

I send from the controller to the jqgrid the information about all internal exceptions. So for example, the error in connection to the SQL server will looks like

在现实世界中,验证用户输入并抛出异常并带有面向应用程序的错误消息.我在demo中特地用了没有这种验证来说明jqGrid会缓存并显示所有类型的异常.

In the real world one verify the users input and throws exception with application oriented error message. I used in the demo specially no such kind of validation to show that all kind of exception will be cached and display by jqGrid.

更新 2:在 答案 你会发现修改后的 VS2010 演示(可从 此处) 演示了 jQuery UI 自动完成的用法.另一个答案扩展代码以导出 Excel 格式的网格.

UPDATED 2: In the answer you will find the modified VS2010 demo (downloadable from here) which demonstrate the usage of jQuery UI Autocomplete. Another answer extend the code more to export the grid contain in Excel format.

这篇关于ASP.NET MVC 2.0 在jqgrid中搜索的实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆