-
30 May 2012 4:43 AM #231
JSON generic type deserialization of method parameters
JSON generic type deserialization of method parameters
Since JSON.NET supports deserialization of generic .NET types, I rewrote the DirectProvider.Execute method to allow deserialization in this generic sense. The trick is to check the expected types of the invoked method via reflection.
Note that I also removed the "SanitizeDates" method since it is no longer necessary. "ParseAsJson" is also not included anymore, but can be added again if needed.
Hope this helps someoneCode:internal object Execute(DirectRequest request) { DirectAction action = this.actions[request.Action]; if (action == null) throw new DirectException("Unable to find action, " + request.Action); DirectMethod method = action.GetMethod(request.Method); if (method == null) throw new DirectException("Unable to find action, " + request.Method); JArray data = (JArray)request.RequestData["data"]; int parameterCount = request.Data != null ? request.Data.Length : data.Count; if (parameterCount == 0) { if (method.Parameters > 0) throw new DirectException("Parameters length does not match"); } else { if (parameterCount > 1 && method.IsForm) { throw new DirectException("Form methods can only have a single parameter."); } else if (parameterCount != method.Parameters) { throw new DirectException("Parameters length does not match"); } } try { object[] param = new object[method.Parameters]; if (request.Data != null) { // lets use given request data param = request.Data; } else { // Deserialize generic JSON to specific .NET method types for (int t = 0; t < param.Length; t++) { Type paramType = method.ParameterInfos[t].ParameterType; param[t] = JsonConvert.DeserializeObject(data[t].ToString(), paramType); } } Type type = action.Type; return method.Method.Invoke(type.Assembly.CreateInstance(type.FullName), param); } catch (TargetInvocationException ex) { // send application exception to browser if (ex.InnerException != null) throw new DirectException(ex.InnerException.ToString()); throw new DirectException(ex.Message); } catch (Exception ex) { throw new DirectException("Error occurred while calling Direct method: " + ex.Message); } }Last edited by christianpapauschek; 30 May 2012 at 4:48 AM. Reason: bugfix
-
26 Jun 2012 3:49 AM #232
Call a function in C# to get json string
Call a function in C# to get json string
Hi
I have a data grid A and another grid B: When user click on a row of A, B will show a grid detail with the ID of the row clicked in A.
I have a function called GetBlogList(int rowIDofA) on server (written in C#) which will return a json string.
How can I call this function and pass the parameter when user click on a row of A by using Ext Direct Router?
Furthermore, do you have a completed guide to use this library?
Thank you
-
28 Aug 2012 4:54 AM #233
Hi All!!! Still on there exception problem. Had dropped the project for a while. Now I'm back still with the same problem. My code is below.
ASP.NetCode:Ext.define('Test.store.Tariff', { extend : 'Ext.data.Store', id : 'Tariffs', autoLoad : false, autoSave : false, autoSync : true, remoteSort : true, pageSize : 100, paramOrder : 'start|limit|page|search', model : 'Test.model.Tariff', proxy : { type : 'direct', reader : { type : 'json', successProperty : 'success', totalProperty : 'total', root : 'data', idProperty : 'Tariff_RowID' }, writer : { type : 'json', encode : false, writeAllFields : true }, api : { create : _tariffHandler.Create_Tariff, read : _tariffHandler.Load_Tariff, update : _tariffHandler.Update_Tariff, destroy : _tariffHandler.Delete_Tariff }, listeners : { exception : function(proxy, response, operation) { Ext.MessageBox.show( { title : 'Remote Exception', msg : operation.getError(), icon : Ext.MessageBox.ERROR, buttons : Ext.Msg.OK }); } }, updateCallback: function (request, success) { if (!request.operation.success && request.operation.hasException()) { console.log(request.operation); Ext.Msg.show( { title : 'Tariff Update Error', msg : request.operation.getError(), buttons : Ext.MessageBox.OK, icon : Ext.MessageBox.ERROR }); } } } });
It is only error message I keep getting is:Code:<DirectMethod()> _ <ParseAsJson()> _ Public Function Update_Tariff(ByVal o As JObject) As Tariff Dim t As Tariff = Nothing Try 'ASSUME NEXT TWO LINES FAIL AND MOVE TO CATCH AND THROUGH EXCEPTION t = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Tariff)(o.ToString()) t.Tariff_Update() Catch ex As DirectException Throw New DirectException("CUSTOMR EXCEPTION MESSAGE BEING SEND HERE") '<--- CUSTOMR EXCEPTION MESSAGE BEING SENT HERE BUT End Try Return t End Function
"Error occurred while calling Direct method: Exception has been thrown by the target of an invocation."
-
7 Sep 2012 6:21 AM #234
Sort and Filter params sent from grid
Sort and Filter params sent from grid
Hi,
does anybody has working copy of this Direct provider with grid/store and remote sorting and filtering?
I see sorters config value is converted to complex object on server side (after json conversion).
I see message about different number of params so my method can't be called...
Is it retired project?
Thanks,
Alex
-
7 Sep 2012 7:10 AM #235
It works with my version of Evan's router.
You have create classes on the server-side that represents the sorters and filters, since the router can't automagically sort it out for you... this parameters need to get passed through and interpreted by your data layer.
e.g. (sanitised and simplied versions for brevity - strings with fixed values should obviously be enums, but not posting the complete solution...):
Think that's enough posted for now...Code:public class SortParam { public string Property { get; set; } public string Direction { get; set; } // One of "ASC"/"DESC" } public class FilterParam { public class FilterDetails { public string Comparison { get; set; } // One of "eq", "lt" or "gt" for date values. public string Type { get; set; } // One of string, boolean, date, numeric, list public string Value { get; set; } public string[] ListFilter { get; set; } } public FilterDetails Data { get; set; } public string Field { get; set; } } public class SearchCriteriaParam // This what Ext.Direct posts for paged grids, say. { public long? Page { get; set; } public long? Start { get; set; } public long? Limit { get; set; } public SortParam[] Sort { get; set; } public FilterParam[] Filter { get; set; } }
Hope that helps.
WestyProduct Architect
Altus Ltd.
-
7 Sep 2012 7:53 AM #236
Super!
Thanks for so quick response. I use paged grid (so called infinite grid
) and I will try it later this evening.
Does it mean if I provide SearchCriteriaParam as the only param on method definition to load data (Read from CRUD) it's converted automatically from set of sent attributes and will be passed as this object?
Thanks,
Alex
-
7 Sep 2012 8:15 AM #237
You'll need it as a param on your method yeah.
Can't remember if anything needed on client... possibly paramOrder and/or paramsAsHash need setting as appropriate; I forget.Product Architect
Altus Ltd.
-
7 Sep 2012 1:20 PM #238
westy,
life is not as simple as I thought after your suggestion
When I run such simple test case like below I see incorrect value on Data property of ResponseObject:
Number of parameters on Data property is higher then number of params passed in JSON.Code:[TestMethod()] public void DeserializeObjectTest() { string value = // {"action":"IncidentListService","method":"Read","data":[1,0,100,[{"property":"TimeOfCall","direction":"DESC"}],null],"type":"rpc","tid":1} "{\"action\":\"IncidentListService\",\"method\":\"Read\",\"data\":[1,0,100,[{\"property\":\"TimeOfCall\",\"direction\":\"DESC\"}],null],\"type\":\"rpc\",\"tid\":1}"; Type type = typeof(DirectRequest); JsonSerializerSettings settings = null; DirectRequest actual = JsonConvert.DeserializeObject(value, type, settings) as DirectRequest; }
This is because Data property is decorated with conversion attribute like below and has some code provided on Direct level that does wrong conversion:
Because of this it causes the exception on Direct level when I try to call method with manually provided list of param...Code:[JsonConverter(typeof(ComplexObjectConverter))] public object[] Data { get; set; }
-
10 Sep 2012 1:09 AM #239
I found source of the problem of course. It's because incorrect conditions flow in code below:
I changed it to this version below with minimal changes (although it should be as effective as switch/case):Code:private object[] ReadArray(JsonReader reader) { ArrayList output = new ArrayList(); while (reader.Read()) { if (reader.TokenType == JsonToken.EndArray) { return output.ToArray(); } if (reader.TokenType == JsonToken.StartArray) { output.Add(ReadArray(reader)); } if (reader.TokenType == JsonToken.StartObject) { output.Add(ReadObject(reader)); } else { output.Add(reader.Value); } } throw new JsonReaderException(); }
The issue was (is) after reading array object the TokeType is set to EndArray and then it executes last operation in message body that is Add(reader.Value)Code:private object[] ReadArray(JsonReader reader) { ArrayList output = new ArrayList(); while (reader.Read()) { if (reader.TokenType == JsonToken.EndArray) { return output.ToArray(); } else if (reader.TokenType == JsonToken.StartArray) { output.Add(ReadArray(reader)); } else if (reader.TokenType == JsonToken.StartObject) { output.Add(ReadObject(reader)); } else { output.Add(reader.Value); } } throw new JsonReaderException(); }
Hope it helps anybody...


Reply With Quote