CECI FONCTIONNE! .. mais a encore besoin d'une chose ...
D'accord, c'est donc à la fois un "commentaire" et une question. Premièrement, voici l'exemple de travail qui peut aider d'autres personnes à rechercher une approche asp.net webmethod/jqGrid. Le code ci-dessous fonctionne complètement pour envoyer/recevoir des paramètres JSON de et vers jqGrid afin d'avoir une pagination, un tri, un filtrage corrects (avec recherche unique) à l'aide de LINQ .. il utilise des morceaux d'ici et là ...
Deuxièmement, ma question est-elle la suivante: Quelqu'un a-t-il déjà déterminé une méthode appropriée pour comptabiliser les opérateurs dynamiques envoyés au code ci-dessous? Etant donné que le client peut potentiellement envoyer "eq" (égal), "cn" (contient) "gt" (supérieur à), il me faut un meilleur moyen de générer de manière dynamique une exception qui ne se limite pas à la construction d'un whereeclause chaîne avec "=" ou "<>", mais peut plutôt englober cela avec la capacité de Dynamic Linq à utiliser .Contains ou .EndsWith, etc.
J'ai peut-être besoin d'une sorte de fonction de construction de prédicats.
code qui gère cela à partir de maintenant (ce qui fonctionne, mais est limité):
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 });
}
Avec le spectacle .........
===============================================
<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",
page: "page",
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', width: 200, searchoptions: { sopt: ['eq', 'ne', '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>
===============================================
[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, 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 });
}
//--- 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; }
}
===============================================
Afin d'avoir des clauses OrderBy dynamiques dans le LINQ, je devais extraire une classe dans mon dossier AppCode appelé 'Dynamic.cs'. Vous pouvez récupérer le fichier de en le téléchargeant ici. Vous trouverez le fichier dans le dossier "DynamicQuery". Ce fichier vous permettra d'utiliser la clause ORDERBY dynamique, car nous ne savons pas dans quelle colonne nous filtrons, à l'exception du chargement initial.
Pour sérialiser le JSON du C-sharp au JS, j'ai incorporé le JSON.net James Newton-King JSON.net DLL trouvé ici: http://json.codeplex.com/releases/view/37810. Après le téléchargement, il y a un "Newtonsoft.Json.Compact.dll" que vous pouvez ajouter dans votre dossier Bin comme référence
Voici mon bloc USING Utilisant System; Utilisant System.Collections; Utilisant System.Collections.Generic; Utilisant System.Linq; Utilisant System.Web.UI.WebControls; À l'aide de System.Web.Services; À l'aide de System.Linq.Dynamic;
Pour les références Javascript, j'utilise les scripts suivants dans leur ordre respectif au cas où cela aiderait certaines personnes: 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
Pour le CSS, j'utilise les nécessités de jqGrid ainsi que le thème de l'interface utilisateur de jQuery: 1) jquery_theme/jquery-ui-1.7.2.custom.css ... 2) ui.jqgrid.css
La clé pour obtenir les paramètres du JS vers le WebMethod sans avoir à analyser une chaîne non sérialisée sur le serveur ou à configurer une logique JS pour changer de méthode pour un nombre différent de paramètres était ce bloc
postData: { searchString: '', searchField: '', searchOper: '' },
Ces paramètres sont toujours définis correctement lorsque vous effectuez une recherche, puis sont réinitialisés à vides lorsque vous les réinitialisez ou si vous souhaitez que la grille ne filtre pas
J'espère que cela aide les autres !!!! Et merci si vous avez le temps de lire et de répondre concernant l’approche dynamique de la création de la localisation avec les opérateurs lors de l’exécution
Considérez cette méthode d'extension, qui convertit une chaîne en MemberExpression:
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;
}
}
La méthode ci-dessous convertit les chaînes que vous avez en une expression Lambda, que vous pouvez utiliser pour filtrer une requête Linq. C'est une méthode générique, avec T comme entité de domaine.
public virtual Expression<Func<T, bool>> CreateExpression<T>(string searchField, string searchString, 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", new Type[] { typeof(string) }), Expression.Constant(searchString));
break;
case "ew":
exp = Expression.Call(propertyAccess, typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) }), Expression.Constant(searchString));
break;
case "gt":
exp = Expression.GreaterThan(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
case "ge":
exp = Expression.GreaterThanOrEqual(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
case "lt":
exp = Expression.LessThan(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
case "le":
exp = Expression.LessThanOrEqual(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
case "eq":
exp = Expression.Equal(propertyAccess, Expression.Constant(searchString.ToType(propertyAccess.Type), propertyAccess.Type));
break;
case "ne":
exp = Expression.NotEqual(propertyAccess, Expression.Constant(searchString, propertyAccess.Type));
break;
default:
return null;
}
return (Expression<Func<T, bool>>)Expression.Lambda(exp, p);
}
catch
{
return null;
}
}
Donc, vous pouvez l'utiliser comme ceci:
db.TBL_USERs.Where(CreateExpression<TBL_USER>("LAST_NAME", "Costa", "eq"));
Donnez cet article un coup d'oeil. Il se concentre sur l’utilisation de jqgrid dans MVC, mais vous pouvez extraire les informations pertinentes.