Cómo implementar búsquedas múltiples en jqGrid

Tengo un jqGrid que estoy usando con asp.Net Web Forms, muestra la información requerida correctamente de la base de datos, sin embargo, también muestra la opción de búsqueda, pero si bash buscar digamos que el nombre es igual al de Lijo, simplemente no aparece ese registro. El registro existe. Sé que me faltan algunas cosas necesarias para buscar seguramente, aquí está el 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 }); });  

Aquí está mi controlador 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; } } } } 

¿Puede alguien ayudarme con esto? Cualquier sugerencia es bienvenida, gracias

En su pregunta, utilizó principalmente el proyecto de demostración de mi respuesta anterior . Todas las otras respuestas posteriores que muestran cómo implementar Búsqueda avanzada, paginación y clasificación en el servidor (por ejemplo, este o este ) utilicé tecnologías ASP.NET más recientes, principalmente ASP.NET MVC. Por otro lado, el código del demos puede decidir en las siguientes partes:

  1. El código del servidor que proporciona alguna interfaz que puede ser utilizada por jqGrid para obtener una respuesta JSON. Puede ser la acción del controlador MVC de ASP.NET, el método WFC, el servicio web WebMethod of ASMX o el controlador ASHX general como usted usa.
  2. El código del servidor que analiza el parámetro de entrada enviado por jqGrid. Los nombres predeterminados de los parámetros son page , rows , sidx , _search , _search , filters . Uno puede cambiar el nombre de los parámetros usando la opción prmNames de jqGrid.
  3. Acceso a la base de datos La parte del código del servidor depende de la tecnología que utilice. Puede ser, por ejemplo, Entity Framework, LINQ to SQL o más antiguo, pero con buen rendimiento SqlCommand con SqlDataReader .
  4. Codificación de resultados como JSON. Uno puede usar, por ejemplo, el estándar JavaScriptSerializer o DataContractJsonSerializer o el alto rendimiento JSON framework Json.NET (conocido como Newtonsoft.JSON). Microsoft usa y admite el serializador Json.NET de código abierto en la nueva versión de ASP.NET MVC 4.0 y ASP.NET Web API. Uno puede incluir Json.NET en el proyecto ASP.NET y puede actualizarlo a la última versión reciente usando NuGet .
  5. Manejando en el servidor las excepciones y reportando la información de error a los clientes (jqGrid) en el formato JSON. El código es un poco diferente dependiendo de la tecnología utilizada en el servidor. El código de cliente en loadError callback de jqGrid debe decodificar la información de error y mostrarla de alguna forma. En el caso del uso de ASP.NET MVC, se muestra en la respuesta cómo implementar el atributo HandleJsonExceptionAttribute que se puede usar como [HandleJsonException] lugar del estándar [HandleError] . En caso de usar WCF, puede usar WebFaultException (ver aquí ). En el caso de ASHX Handler General, se puede usar Application_Error of Global.asax para este fin.
  6. Opcionalmente se puede incluir en la configuración del código del servidor de ETag en el encabezado HTTP. Permite controlar la caché del lado del cliente en el lado del servidor. Si el cliente necesita datos JSON previamente devueltos del servidor, enviará automáticamente la parte If-None-Match en la solicitud HTTP al servidor que contiene ETag de la respuesta del servidor anterior. El servidor puede verificar si los datos del servidor han cambiado desde la última respuesta. Al final, el servidor devolverá los nuevos datos JSON o una respuesta vacía que permite al cliente utilizar los datos de la respuesta anterior.
  7. Uno necesita escribir código JavaScript que cree jqGrid.

Hice el proyecto de demostración que demuestra todos los pasos anteriores. Contiene una pequeña base de datos que llené con información sobre algunos de los famosos matemáticos. La demostración muestra la grilla enter image description here donde uno puede usar clasificación, paginación, filtro de barra de herramientas o búsqueda avanzada. En caso de algún error (por ejemplo, si detiene el Servicio de Windows “SQL Server (SQLEXPRESS)”) verá el mensaje de error como el siguiente: enter image description here

El código C # que implementa ASHX handle en la demostración es

 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 restre 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; } } } } 

Utiliza Newtonsoft.Json para la serialización JSON y utiliza el hash MD5 como ETag .

El método MyData.GetDataForJqGrid proporciona los datos de la base de datos. En la demostración utilizo principalmente el código de la respuesta , entonces uso Entity Framework para acceder a la base de datos:

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

donde la clase 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 restre 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; } } } 

El código de Global.asax.cs es

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

En el lado del cliente, utilicé la página HTML pura para mostrar, en su mayor parte, claramente que puede incluir la solución en cualquier proyecto de formulario web inclusivo de su proyecto. La página tiene el siguiente código

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

donde está 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" }); });

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

ACTUALIZADO : Hice algunas pequeñas mejoras: json2.js incluidos (ver aquí ) para admitir JSON.stringify en navegadores web antiguos, formato de fecha fijo en jQuery UI Datepicker y soporte incluido para DateType y DateType? ( System.Nullable ) en la clase Filters . Para que pueda descargar la versión actual del proyecto desde la misma ubicación .