好吧,所以这是一个“评论”和问题。首先,是可以帮助其他人搜索asp.net webmethod / jqGrid方法的工作示例。下面的代码完全工作,发送/接收JSON参数从和到jqGrid为了有正确的分页,排序,过滤(使用单一搜索)利用LINQ ..它使用片段从这里和那里…
第二,是我的问题:
有没有人确定一个适当的方法来计算发送到codebehind的动态运算符?由于客户端可能发送“eq”(等于),“cn”(包含)“gt”(大于),我需要一个更好的方式动态生成一个whereclause,不仅限于我构建一个whereclause字符串“=”或“<>”,而是可以包括与动态Linq利用.Contains或.EndsWith等的能力。
我可能需要某种谓词构建器函数。
代码,处理此截至现在(它的工作,但是有限):
if (isSearch) { searchOper = getOperator(searchOper); // need to associate correct operator to value sent from jqGrid string whereClause = String.Format("{0} {1} {2}",searchField,searchOper,"@" + searchField); //--- associate value to field parameter Dictionary<string,object> param = new Dictionary<string,object>(); param.Add("@" + searchField,searchString); query = query.Where(whereClause,new object[1] { param }); }
随着节目………
==================================================
首先,JAVASCRIPT
<script type="text/javascript"> $(document).ready(function() { var grid = $("#grid"); $("#grid").jqGrid({ // setup custom parameter names to pass to server prmNames: { search: "isSearch",nd: null,rows: "numRows",page: "page",sort: "sortField",order: "sortOrder" },// add by default to avoid webmethod parameter conflicts postData: { searchString: '',searchField: '',searchOper: '' },// setup ajax call to webmethod datatype: function(postdata) { $(".loading").show(); // make sure we can see loader text $.ajax({ url: 'PageName.aspx/getGridData',type: "POST",contentType: "application/json; charset=utf-8",data: JSON.stringify(postdata),dataType: "json",success: function(data,st) { if (st == "success") { var grid = $("#grid")[0]; grid.addJSONData(JSON.parse(data.d)); } },error: function() { alert("Error with AJAX callback"); } }); },// this is what jqGrid is looking for in json callback jsonReader: { root: "rows",total: "totalpages",records: "totalrecords",cell: "cell",id: "id",//index of the column with the PK in it userdata: "userdata",repeatitems: true },colNames: ['Id','First Name','Last Name'],colModel: [ { name: 'id',index: 'id',width: 55,search: false },{ name: 'fname',index: 'fname',width: 200,searchoptions: { sopt: ['eq','ne','cn']} },{ name: 'lname',index: 'lname','cn']} } ],rowNum: 10,rowList: [10,20,30],pager: jQuery("#pager"),sortname: "fname",sortorder: "asc",viewrecords: true,caption: "Grid Title Here",gridComplete: function() { $(".loading").hide(); } }).jqGrid('navGrid','#pager',{ edit: false,add: false,del: false },{},// default settings for edit {},// add {},// delete { cloSEOnEscape: true,closeAfterSearch: true},//search {} ) }); </script>
==================================================
第二,C#WEBMETHOD
[WebMethod] public static string getGridData(int? numRows,int? page,string sortField,string sortOrder,bool isSearch,string searchField,string searchString,string searchOper) { string result = null; MyDataContext db = null; try { //--- retrieve the data db = new MyDataContext("my connection string path"); var query = from u in db.TBL_USERs select new User { id = u.REF_ID,lname = u.LAST_NAME,fname = u.FIRST_NAME }; //--- determine if this is a search filter if (isSearch) { searchOper = getOperator(searchOper); // need to associate correct operator to value sent from jqGrid string whereClause = String.Format("{0} {1} {2}","@" + searchField); //--- associate value to field parameter Dictionary<string,object>(); param.Add("@" + searchField,searchString); query = query.Where(whereClause,new object[1] { param }); } //--- setup calculations int pageIndex = page ?? 1; //--- current page int pageSize = numRows ?? 10; //--- number of rows to show per page int totalRecords = query.Count(); //--- number of total items from query int totalPages = (int)Math.Ceiling((decimal)totalRecords / (decimal)pageSize); //--- number of pages //--- filter dataset for paging and sorting IQueryable<User> orderedRecords = query.OrderBy(sortfield); IEnumerable<User> sortedRecords = orderedRecords.ToList(); if (sortorder == "desc") sortedRecords= sortedRecords.Reverse(); sortedRecords = sortedRecords .Skip((pageIndex - 1) * pageSize) //--- page the data .Take(pageSize); //--- format json var jsonData = new { totalpages = totalPages,//--- number of pages page = pageIndex,//--- current page totalrecords = totalRecords,//--- total items rows = ( from row in sortedRecords select new { i = row.id,cell = new string[] { row.id.ToString(),row.fname,row.lname } } ).ToArray() }; result = Newtonsoft.Json.JsonConvert.SerializeObject(jsonData); } catch (Exception ex) { Debug.WriteLine(ex); } finally { if (db != null) db.Dispose(); } return result; } /* === User Object =========================== */ public class User { public int id { get; set; } public string lname { get; set; } public string fname { get; set; } }
==================================================
第三,事实
>为了在LINQ中有动态的OrderBy子句,我不得不把一个类拖到我的AppCode文件夹,名为’Dynamic.cs’。您可以从downloading here检索文件。您将在“DynamicQuery”文件夹中找到该文件。该文件将使您能够使用动态ORDERBY子句,因为我们不知道除了初始加载之外,我们要过滤的列。
>为了将JSON从C-sharp序列化到JS,我引入了位于这里的James Newton-King JSON.net DLL:下载后,有一个“Newtonsoft.Json.Compact.dll”,您可以添加在您的Bin文件夹中作为参考
>这是我的USING的块
使用系统;
使用System.Collections;
使用System.Collections.Generic;
使用System.Linq;
使用System.Web.UI.WebControls;
使用System.Web.Services;
使用System.Linq.Dynamic;
>对于Javascript引用,我使用以下脚本各自的顺序,以便帮助一些人:1)jquery-1.3.2.min.js … 2)jquery-ui-1.7.2.custom.min .js … 3)json.min.js … 4)i18n / grid.locale-en.js … 5)jquery.jqGrid.min.js
>对于CSS,我使用jqGrid的必需品以及jQuery UI主题:1)jquery_theme / jquery-ui-1.7.2.custom.css … 2)ui.jqgrid.css
将参数从JS获取到WebMethod的关键,而不必解析后端的非序列化字符串或者必须设置一些JS逻辑来切换不同数量的参数的方法是这个块
postData: { searchString: '',
当您实际执行搜索时,这些参数仍将正确设置,然后在“重置”或希望网格不进行任何过滤时将其重置为空
解决方法
public static class StringExtensions { public static MemberExpression ToMemberExpression(this string source,ParameterExpression p) { if (p == null) throw new ArgumentNullException("p"); string[] properties = source.Split('.'); Expression expression = p; Type type = p.Type; foreach (var prop in properties) { var property = type.GetProperty(prop); if (property == null) throw new ArgumentException("Invalid expression","source"); expression = Expression.MakeMemberAccess(expression,property); type = property.PropertyType; } return (MemberExpression)expression; } }
下面的方法将您拥有的字符串转换为Lambda表达式,您可以使用它来过滤Linq查询。它是一个通用的方法,用T作为域实体。
public virtual Expression<Func<T,bool>> CreateExpression<T>(string searchField,string searchOper) { Expression exp = null; var p = Expression.Parameter(typeof(T),"p"); try { Expression propertyAccess = searchField.ToExpression(p); switch (searchOper) { case "bw": exp = Expression.Call(propertyAccess,typeof(string).GetMethod("StartsWith",new Type[] { typeof(string) }),Expression.Constant(searchString)); break; case "cn": exp = Expression.Call(propertyAccess,typeof(string).GetMethod("Contains",Expression.Constant(searchString)); break; case "ew": exp = Expression.Call(propertyAccess,typeof(string).GetMethod("EndsWith",Expression.Constant(searchString)); break; case "gt": exp = Expression.GreaterThan(propertyAccess,Expression.Constant(searchString,propertyAccess.Type)); break; case "ge": exp = Expression.GreaterThanOrEqual(propertyAccess,propertyAccess.Type)); break; case "lt": exp = Expression.LessThan(propertyAccess,propertyAccess.Type)); break; case "le": exp = Expression.LessThanOrEqual(propertyAccess,propertyAccess.Type)); break; case "eq": exp = Expression.Equal(propertyAccess,Expression.Constant(searchString.ToType(propertyAccess.Type),propertyAccess.Type)); break; case "ne": exp = Expression.NotEqual(propertyAccess,propertyAccess.Type)); break; default: return null; } return (Expression<Func<T,bool>>)Expression.Lambda(exp,p); } catch { return null; } }
所以,你可以这样使用它:
db.TBL_USERs.Where(CreateExpression<TBL_USER>("LAST_NAME","Costa","eq"));