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'
的 imgpath
和 multipleSearch
参数,它们是未知的或默认的。
更新: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
搜索选项,那么搜索对话框将在请求中发送_search
、searchField
、searchString
、searchOper
(大小写很重要)参数到服务器。如果没有multipleSearch:true
,搜索工具栏的格式将是其他格式:发送到服务器的参数将类似于列名(column2
或/和column2
)。因此,主要使用multipleSearch:true
,并在服务器方法中将filters
参数转换为JavaScriptSerializer
或DataContractJsonSerializer
的对象。
@Sue:我的主要想法是在实体框架的情况下使用ObjectQuery<T>
比使用IQueryable<T>
更好,因为IQueryable<T>
不支持您作为输入接收的字符串参数jq网格。如果您使用IQueryable<T>
,则必须在您的项目中包含System.Linq.Dynamic.dll
或像tpeczek 这样的LINQ 动态查询库的源代码(它有4000 多行代码)。在使用实体框架的情况下,ObjectQuery<T>
的使用更有效。这是我的主要声明。
@Learning:上面的代码就是这样做的。参见DynamicGridData
的代码。您可以删除部分代码。如果您是初学者,我建议您准确考虑是否真的需要 服务器端 分页。客户端分页/排序/过滤对大约 1000 行的工作速度足够快。尝试使用 4000 和 40000 行的 the demo 和 this one
@Learning:请更准确地写出您需要的内容。 ASP.NET MVC 仍然是 ASP.NET。您询问了“在 asp.net 中”的示例。你到底是什么技术?例如,another answer 提供了一个使用 ASHX 的示例(IHttpHandler
与 ProcessRequest
和 IsReusable
)。可能这就是您要找的东西?【参考方案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 最佳实践。
其他一些小东西,例如<style type="text/css">/* fix the size of the pager */input.ui-pg-input width: auto; </style>
或使用height:'100%'
而不是height:'auto'
(由于IE9 错误)可以改进您的示例。 jqGrid 不支持width:'auto'
的使用。 '#jqgpProducts'
的用法不如$('#jqgpProducts')
好。不应该包含默认属性,如align:'left'
、search: true
、stype: 'text'
等等。我只想在 jqGrid 的最佳实践下进一步解释我的意思。
还有一个建议:如果您修改 MVC 项目的默认 Site.css
或在 @ 之后的 _Layout.cshtml
中包含 <style type="text/css"> table border-style:none; border-collapse:separate; table td border-style:none; </style>
,则可以从示例的 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)