Como implementar múltiplas pesquisas no jqGrid

Eu tenho um jqGrid que estou usando com asp.Net Web Forms, ele mostra as informações necessárias corretamente a partir do database, no entanto, mostra a opção de pesquisa também, mas se eu tentar pesquisar vamos dizer primeiro nome que é igual a Lijo, simplesmente não aparece esse registro. O registro existe. Sei que estou perdendo algumas coisas necessárias para pesquisar com segurança, aqui está o código

 $(function() { $("#UsersGrid").jqGrid({ url: 'ModCust.ashx', datatype: 'json', height: 250, width: 800, colNames: ['Application No', 'First Name', 'Middle Name', 'Last Name'], colModel: [ { name: 'cApplicationNo', index: 'cApplicationNo', width: 100, sortable: true}, { name: 'cFirstName', width: 100, sortable: true}, { name: 'cMiddleName', width: 100, sortable: true }, { name: 'cLastName', width: 100, sortable: true }, ], cmTemplate: { title: false}, rowNum: 10, rowList: [10, 20, 30], pager: '#UsersGridPager', sortname: 'cApplicationNo', viewrecords: true, sortorder: 'asc', caption: 'Customer Details' }); $("#UsersGrid").jqGrid('navGrid', '#UsersGridPager', { edit: false, add: false, del: false }); });  

Aqui está o meu manipulador ModCust.ashx

 using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Data.SqlClient; using System.Web; using System.Web.Script.Serialization; namespace CwizBankApp { public struct JQGridResults { public int page; public int total; public int records; public JQGridRow[] rows; } public struct JQGridRow { public string id; public string[] cell; } [Serializable] public class User { public string ApplicationNo { get; set; } public string FirstName { get; set; } public string MiddleName { get; set; } public string LastName { get; set; } } ///  /// Summary description for $codebehindclassname$ ///  public class ModCust : IHttpHandler { public void ProcessRequest(HttpContext context) { HttpRequest request = context.Request; HttpResponse response = context.Response; string _search = request["_search"]; string numberOfRows = request["rows"]; string pageIndex = request["page"]; string sortColumnName = request["sidx"]; string sortOrderBy = request["sord"]; int totalRecords; //Collection users = GetDummyUsers(numberOfRows, pageIndex, sortColumnName, sortOrderBy, out totalRecords); Collection users = GetUsers(numberOfRows, pageIndex, sortColumnName, sortOrderBy, out totalRecords); string output = BuildJQGridResults(users, Convert.ToInt32(numberOfRows), Convert.ToInt32(pageIndex), Convert.ToInt32(totalRecords)); response.Write(output); } private string BuildJQGridResults(Collection users, int numberOfRows, int pageIndex, int totalRecords) { JQGridResults result = new JQGridResults(); List rows = new List(); foreach (User user in users) { JQGridRow row = new JQGridRow(); row.id = user.ApplicationNo; row.cell = new string[4]; row.cell[0] = user.ApplicationNo; row.cell[1] = user.FirstName; row.cell[2] = user.MiddleName; row.cell[3] = user.LastName; rows.Add(row); } result.rows = rows.ToArray(); result.page = pageIndex; result.total = (totalRecords + numberOfRows - 1) / numberOfRows; result.records = totalRecords; return new JavaScriptSerializer().Serialize(result); } private Collection GetDummyUsers(string numberOfRows, string pageIndex, string sortColumnName, string sortOrderBy, out int totalRecords) { var data = new Collection { new User(){ FirstName = "Bill", LastName = "Gates", ApplicationNo= "1", MiddleName = "Bill Gates"} }; totalRecords = data.Count; return data; } private Collection GetUsers(string numberOfRows, string pageIndex, string sortColumnName, string sortOrderBy, out int totalRecords) { Collection users = new Collection(); string connectionString = "Server=Server;Database=CwizData;Trusted_Connection=True"; using (SqlConnection connection = new SqlConnection(connectionString)) { using (SqlCommand command = new SqlCommand()) { command.Connection = connection; command.CommandText = "select cApplicationNo,cFirstName,cMiddleName,cLastName from Data_Customer_Log"; command.CommandType = CommandType.Text; // StoredProcedure; SqlParameter paramPageIndex = new SqlParameter("@PageIndex", SqlDbType.Int); paramPageIndex.Value = Convert.ToInt32(pageIndex); command.Parameters.Add(paramPageIndex); SqlParameter paramColumnName = new SqlParameter("@SortColumnName", SqlDbType.VarChar, 50); paramColumnName.Value = sortColumnName; command.Parameters.Add(paramColumnName); SqlParameter paramSortorderBy = new SqlParameter("@SortOrderBy", SqlDbType.VarChar, 4); paramSortorderBy.Value = sortOrderBy; command.Parameters.Add(paramSortorderBy); SqlParameter paramNumberOfRows = new SqlParameter("@NumberOfRows", SqlDbType.Int); paramNumberOfRows.Value = Convert.ToInt32(numberOfRows); command.Parameters.Add(paramNumberOfRows); SqlParameter paramTotalRecords = new SqlParameter("@TotalRecords", SqlDbType.Int); totalRecords = 0; paramTotalRecords.Value = totalRecords; paramTotalRecords.Direction = ParameterDirection.Output; command.Parameters.Add(paramTotalRecords); connection.Open(); using (SqlDataReader dataReader = command.ExecuteReader()) { User user; while (dataReader.Read()) { user = new User(); user.ApplicationNo =Convert.ToString(dataReader["cApplicationNo"]); user.FirstName = Convert.ToString(dataReader["cFirstName"]); user.MiddleName = Convert.ToString(dataReader["cMiddleName"]); user.LastName = Convert.ToString(dataReader["cLastName"]); users.Add(user); } } //totalRecords =(int)(paramTotalRecords.Value); // totalRecords = 0; } return users; } } public bool IsReusable { get { return false; } } } } 

Alguém pode me ajudar com isso, Qualquer sugestão é bem-vinda, obrigado

Na sua pergunta você usou principalmente o projeto de demonstração da minha resposta antiga . Todas as outras respostas posteriores, que mostram como implementar a pesquisa avançada, paginação e sorting no servidor (por exemplo, este ou este ) eu usei tecnologias ASP.NET mais recentes, principalmente ASP.NET MVC. Por outro lado, o código das demonstrações pode decidir nas seguintes partes:

  1. O código do servidor que fornece alguma interface que pode ser usada pelo jqGrid para obter resposta JSON. Pode ser a ação do controlador ASP.NET MVC, o método WFC, o WebMethod do serviço da web ASMX ou o General ASHX Handler como você usa.
  2. O código do servidor que analisa o parâmetro de input enviado pelo jqGrid. Os nomes padrão dos parâmetros são page , rows , sidx , sord , _search , filters . Pode-se renomear os parâmetros usando a opção prmNames do jqGrid.
  3. Acesso ao database. A parte do código do servidor depende da tecnologia que você usa. Pode ser, por exemplo, Entity Framework, LINQ to SQL ou mais antigo, mas com bom desempenho SqlCommand com SqlDataReader .
  4. Codificação de resultados como JSON. Pode-se usar, por exemplo, o JavaScriptSerializer padrão ou o DataContractJsonSerializer ou o framework JSON de alto desempenho Json.NET (conhecido como Newtonsoft.JSON). A Microsoft usa e suporta o serializador Json.NET de software livre na nova versão do ASP.NET MVC 4.0 e na API da Web do ASP.NET. Pode-se include o Json.NET no projeto ASP.NET e atualizá-lo para a última versão recente usando o NuGet .
  5. Manipulando no servidor as exceções e relatando as informações de erro para os clientes (jqGrid) no formato JSON. O código é um pouco diferente dependendo da tecnologia usada no servidor. O código do cliente no retorno de chamada loadError do jqGrid deve decodificar as informações de erro e exibi-las de alguma forma. No caso do uso da ASP.NET MVC eu mostrei na resposta como implementar o atributo HandleJsonExceptionAttribute que pode ser usado como [HandleJsonException] invés do padrão [HandleError] . No caso de uso WCF, pode-se usar WebFaultException (veja aqui ). No caso do General ASHX Handler, pode-se usar o Application_Error do Global.asax para o propósito.
  6. Opcionalmente, pode-se include na configuração do código do servidor ETag no header HTTP. Permite controlar o cache do lado do cliente no lado do servidor. Se o cliente precisar de dados JSON anteriormente retornados do servidor, ele enviará automaticamente a parte If-None-Match na solicitação HTTP para o servidor que contém ETag da resposta anterior do servidor. O servidor pode verificar se os dados do servidor foram alterados desde a última resposta. No final, o servidor retornará os novos dados JSON ou uma resposta vazia, permitindo que o cliente use os dados da resposta antiga.
  7. É preciso escrever código JavaScript que crie o jqGrid.

Fiz o projeto de demonstração que demonstra todas as etapas acima. Contém pequeno database que eu encho com informação sobre alguns dos matemáticos famosos. A demonstração exibe a grade insira a descrição da imagem aqui onde é possível usar sorting, paginação, filtragem de barra de ferramentas ou pesquisa avançada. Em caso de algum erro (por exemplo, se você parar o serviço do Windows “SQL Server (SQLEXPRESS)”), você verá a mensagem de erro como o seguinte: insira a descrição da imagem aqui

O código C # que implementa o manipulador ASHX na demonstração é

 using System; using System.Globalization; using System.Net; using System.Security.Cryptography; using System.Text; using System.Web; using Newtonsoft.Json; namespace jqGridASHX { // ReSharper disable InconsistentNaming public class jqGridData : IHttpHandler { // ReSharper restore InconsistentNaming public void ProcessRequest (HttpContext context) { // to be able to use context.Response.Cache.SetETag later we need the following: context.Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate); // to use with HTTP GET we want be sure that caching of data work correct // so we request revalidation of data by setting in HTTP header the line // "Cache-Control: private, max-age=0" context.Response.Cache.SetMaxAge (new TimeSpan (0)); string numberOfRows = context.Request["rowsPerPage"]; int nRows, iPage; if (String.IsNullOrEmpty (numberOfRows) || !int.TryParse (numberOfRows, NumberStyles.Integer, CultureInfo.InvariantCulture, out nRows)) nRows = 10; // default value string pageIndex = context.Request["pageIndex"]; if (String.IsNullOrEmpty(pageIndex) || !int.TryParse(pageIndex, NumberStyles.Integer, CultureInfo.InvariantCulture, out iPage)) iPage = 10; // default value string sortColumnName = context.Request["sortByColumn"]; string sortOrder = context.Request["sortOrder"]; string search = context.Request["isSearching"]; string filters = context.Request["filters"]; // we can use high-performance Newtonsoft.Json string str = JsonConvert.SerializeObject ( MyData.GetDataForJqGrid ( nRows, iPage, sortColumnName, !String.IsNullOrEmpty (sortOrder) && String.Compare (sortOrder, "desc", StringComparison.Ordinal) == 0 ? MyData.SortOrder.Desc : MyData.SortOrder.Asc, search != null && String.Compare (search, "true", StringComparison.Ordinal) == 0, filters)); context.Response.ContentType = "application/json"; // calculate MD5 from the returned data and use it as ETag byte[] hash = MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(str)); string newETag = Convert.ToBase64String(hash); // compare ETag of the data which already has the client with ETag of response string incomingEtag = context.Request.Headers["If-None-Match"]; if (String.Compare(incomingEtag, newETag, StringComparison.Ordinal) == 0) { // we don't need return the data which the client already have context.Response.SuppressContent = true; context.Response.StatusCode = (int)HttpStatusCode.NotModified; return; } context.Response.Cache.SetETag(newETag); context.Response.Write(str); } public bool IsReusable { get { return false; } } } } 

Ele usa Newtonsoft.Json para serialização JSON e usa hash MD5 como ETag .

O método MyData.GetDataForJqGrid fornece os dados do database. Na demonstração eu uso principalmente o código da resposta , então eu uso o Entity Framework para acessar o database:

 using System; using System.Data.Objects; using System.Globalization; using System.Linq; using Newtonsoft.Json; namespace jqGridASHX { public static class MyData { public enum SortOrder { Asc, Desc } public static Object GetDataForJqGrid(int nRows, int iPage, string sortColumnName, SortOrder sortOrder, bool isSearch, string filters) { var context = new MyDatabaseEntities(); var f = (!isSearch || string.IsNullOrEmpty(filters)) ? null : JsonConvert.DeserializeObject(filters); ObjectQuery filteredQuery = f == null ? context.Users : f.FilterObjectSet(context.Users); filteredQuery.MergeOption = MergeOption.NoTracking; // we don't want to update the data var totalRecords = filteredQuery.Count(); var pagedQuery = filteredQuery.Skip( "it." + (String.IsNullOrEmpty(sortColumnName) ? "Id" : sortColumnName) + " " + sortOrder, "@skip", new ObjectParameter("skip", (iPage - 1) * nRows)) .Top("@limit", new ObjectParameter("limit", nRows)); // to be able to use ToString() below which is NOT exist in the LINQ to Entity // we should include in queryDetails only the properies which we will use below var queryDetails = (from item in pagedQuery select new { item.Id, item.FirstName, item.LastName, item.Birthday }).ToArray(); return new { total = (totalRecords + nRows - 1) / nRows, page = iPage, records = totalRecords, rows = (from item in queryDetails select new[] { // In the demo we send Id as the 4-th element of row array. // The value will be not displayed in the grid, but used as rowid // (the id attribute of the  in the ) item.FirstName, item.LastName, item.Birthday == null? String.Empty : ((DateTime)item.Birthday).ToString("yyyy-MM-dd"), item.Id.ToString (CultureInfo.InvariantCulture) }).ToArray() }; } } }

onde a class Filters

 using System; using System.Collections.Generic; using System.Data.Objects; using System.Text; namespace jqGridASHX { public class Filters { // ReSharper disable InconsistentNaming 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 rules { get; set; } // ReSharper restore InconsistentNaming 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 FilterObjectSet(ObjectQuery inputQuery) where T : class { if (rules.Count < = 0) return inputQuery; var sb = new StringBuilder(); var objParams = new List(rules.Count); foreach (var rule in rules) { var 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); ObjectParameter param; switch (propertyInfo.PropertyType.FullName) { case "System.Int32": // int param = new ObjectParameter("p" + iParam, Int32.Parse(rule.data)); break; case "System.Int64": // bigint param = new ObjectParameter("p" + iParam, Int64.Parse(rule.data)); break; case "System.Int16": // smallint param = new ObjectParameter("p" + iParam, Int16.Parse(rule.data)); break; case "System.SByte": // tinyint param = new ObjectParameter("p" + iParam, SByte.Parse(rule.data)); break; case "System.Single": // Edm.Single, in SQL: float param = new ObjectParameter("p" + iParam, Single.Parse(rule.data)); break; case "System.Double": // float(53), double precision param = new ObjectParameter("p" + iParam, Double.Parse(rule.data)); break; case "System.Boolean": // Edm.Boolean, in SQL: bit param = new ObjectParameter("p" + iParam, String.Compare(rule.data, "1", StringComparison.Ordinal) == 0 || String.Compare(rule.data, "yes", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(rule.data, "true", StringComparison.OrdinalIgnoreCase) == 0); break; default: // TODO: Extend to other data types // binary, date, datetimeoffset, // decimal, numeric, // money, smallmoney // and so on. // Below in the example for DateTime and the nullable DateTime if (String.Compare(propertyInfo.PropertyType.FullName, typeof(DateTime?).FullName, StringComparison.Ordinal) == 0 || String.Compare(propertyInfo.PropertyType.FullName, typeof(DateTime).FullName, StringComparison.Ordinal) == 0) { // we use below en-US locale directly param = new ObjectParameter("p" + iParam, DateTime.Parse(rule.data, new CultureInfo("en-US"), DateTimeStyles.None)); } else { param = new ObjectParameter("p" + iParam, rule.data); } break; } objParams.Add(param); } var filteredQuery = inputQuery.Where(sb.ToString()); foreach (var objParam in objParams) filteredQuery.Parameters.Add(objParam); return filteredQuery; } } } 

O código do Global.asax.cs é

 using System; using System.Collections.Generic; using System.Net; using System.Reflection; using System.Web; using Newtonsoft.Json; namespace jqGridASHX { internal class ExceptionInformation { public string Message { get; set; } public string Source { get; set; } public string StackTrace { get; set; } public string ErrorCode { get; set; } } public class Global : HttpApplication { protected void Application_Error(object sender, EventArgs e) { if (Request.ContentType.Contains("application/json")) { Response.Clear(); Response.StatusCode = (int)HttpStatusCode.InternalServerError; Response.Cache.SetMaxAge(new TimeSpan(0)); Response.ContentType = "application/json"; var exInfo = new List(); for (var ex = Server.GetLastError(); ex != null; ex = ex.InnerException) { PropertyInfo propertyInfo = ex.GetType().GetProperty ("HResult"); exInfo.Add (new ExceptionInformation { Message = ex.Message, Source = ex.Source, StackTrace = ex.StackTrace, ErrorCode = propertyInfo != null && propertyInfo.GetValue (ex, null) is int ? "0x" + ((int)propertyInfo.GetValue (ex, null)).ToString("X") : String.Empty }); } Response.Write(JsonConvert.SerializeObject(exInfo)); Context.Server.ClearError(); } } } } 

No lado do cliente, usei uma página HTML pura para mostrar claramente que você pode include a solução em qualquer projeto Web Form inclusivo do seu projeto. A página tem o seguinte código

 < !DOCTYPE html>   https://stackoverflow.com/q/10698254/315935               

onde MyPage.js é

 ///  ///  ///  ///  $(function () { "use strict"; $("#list").jqGrid({ url: "jqGridData.ashx", colNames: ["First Name", "Last Name", "Birthday"], colModel: [ { name: "FirstName", width: 200 }, { name: "LastName", width: 180 }, { name: "Birthday", width: 100, formatter: "date", align: "center", searchoptions: { sopt: ["eq", "ne", "lt", "le", "gt", "ge"], dataInit: function (elem) { $(elem).datepicker({ dateFormat: "m/d/yy", minDate: "1/1/1753", defaultDate: "4/30/1777", autoSize: true, changeYear: true, changeMonth: true, showButtonPanel: true, showWeek: true }); }} } ], jsonReader: { cell: "", // The Id value will be sent as the 4-th element of row array. // The value will be not displayed in the grid, but used as rowid // (the id attribute of the  in the ) id: "3" }, rowNum: 10, rowList: [10, 20, 30], pager: "#pager", rownumbers: true, viewrecords: true, sortname: "Birthday", sortorder: "desc", caption: "Famous Mathematicians" }).jqGrid("navGrid", "#pager", { edit: false, add: false, del: false }) .jqGrid('filterToolbar', { stringResult: true, searchOnEnter: true, defaultSearch: "cn" }); });

e Common.js :

 ///  ///  ///  $.extend($.jgrid.defaults, { height: "100%", altRows: true, altclass: "myAltRowClass", shrinkToFit: false, gridview: true, rownumbers: true, viewrecords: true, datatype: "json", sortable: true, scrollrows: true, headertitles: true, loadui: "block", viewsortcols: [false, "vertical", true], prmNames: { nd: null, page: "pageIndex", rows: "rowsPerPage", sort: "sortByColumn", order: "sortOrder", search: "isSearching" }, ajaxGridOptions: { contentType: "application/json" }, ajaxRowOptions: { contentType: "application/json", type: "PUT", async: true }, ajaxSelectOptions: { contentType: "application/json", dataType: "JSON" }, serializeRowData: function (data) { var propertyName, propertyValue, dataToSend = {}; for (propertyName in data) { if (data.hasOwnProperty(propertyName)) { propertyValue = data[propertyName]; if ($.isFunction(propertyValue)) { dataToSend[propertyName] = propertyValue(); } else { dataToSend[propertyName] = propertyValue; } } } return JSON.stringify(dataToSend); }, resizeStop: function () { var $grid = $(this.bDiv).find('>:first-child>.ui-jqgrid-btable:last-child'), shrinkToFit = $grid.jqGrid('getGridParam', 'shrinkToFit'), saveState = $grid.jqGrid('getGridParam', 'saveState'); $grid.jqGrid('setGridWidth', this.newWidth, shrinkToFit); if ($.isFunction(saveState)) { saveState.call($grid[0]); } }, gridComplete: function () { $("#" + this.id + "_err").remove(); }, loadError: function (xhr) { var response = xhr.responseText, errorDetail, errorHtml, i, l, errorDescription; if (response.charAt(0) === '[' && response.charAt(response.length - 1) === ']') { errorDetail = $.parseJSON(xhr.responseText); var errorText = ""; for (i = 0, l = errorDetail.length; i < l; i++) { if (errorText.length !== 0) { errorText += "
"; } errorDescription = errorDetail[i]; errorText += "" + errorDescription.Source + ""; if (errorDescription.ErrorCode) { errorText += " (ErrorCode: " + errorDescription.ErrorCode + ")"; } errorText += ": " + errorDescription.Message; } errorHtml = '

' + errorText + '

'; $("#" + this.id + "_err").remove(); $(this).closest(".ui-jqgrid").before(errorHtml); } } }); $.extend($.jgrid.search, { multipleSearch: true, recreateFilter: true, closeOnEscape: true, searchOnEnter: true, overlay: 0 });

ATUALIZADO : Fiz algumas pequenas melhorias: incluí o json2.js (veja aqui ) para suportar o JSON.stringify em navegadores antigos, o formato fixo da data no jQuery UI Datepicker e suporte incluído para DateType e DateType? ( System.Nullable ) na class Filters . Então você pode baixar a versão atual do projeto no mesmo local .