-
18 Mar 2010 9:26 AM #141
Thought I'd post the code sample to demonstrate how I got it working. This is from my current sandbox, so the names are not the same as in previous examples, but you'll get the idea. [Edit: Viewers take note that this example is not fully implemented and is only a proof of concept. If EvanT doesn't implement it fully, I will later and post my changes]
Code:// -<Temporary .NET Workarounds> --------------------------- // ID Fix for retrieval Saturn.Remote.UserHandler.id = "Saturn.Remote.UserHandler"; // Mechanism to get param count Saturn.Remote.UserHandler.getMethodArgumentLength = function(action, method) { //TODO: convert to faster mechanism (dictionary-style instead of iteration) for (var mthd inthis.actions[action]) { if (this.actions[action][mthd].name == method) { returnthis.actions[action][mthd].len; } } } // -</Temporary .NET Workarounds> --------------------------- // -<Consumer Specifics> --------------------------- var dummy = 0; Saturn.Remote.UserHandler.acquireMetaData = function() { dummy++; return"Change #"+dummy; } // -</Consumer Specifics> --------------------------- // -<Standard Implementation> --------------------------- Ext.Direct.addProvider(Saturn.Remote.UserHandler); // -</Standard Implementation> --------------------------- // -<Client Side Upgrades> --------------------------- Ext.Direct.getProvider("Saturn.Remote.UserHandler").on("beforecall", preProcessCall); // -</Client Side Upgrades> ------------ // -<Ext.Direct .NET Upgrades> --------------------------- function preProcessCall(provider, transaction) { //TODO: Currently only supports the first parameter as MetaDataParam if (Ext.isDefined(provider.acquireMetaData)) { var mLength = provider.getMethodArgumentLength(transaction.action,transaction.method); if (transaction.args.length == mLength + 1) { // its fully defined, replace values transaction.args[0] = provider.acquireMetaData(); transaction.data[0] = transaction.args[0]; } else { // its not full, we need to fix it. transaction.args.splice(0, 0, provider.acquireMetaData()); // Add the missing parameter transaction.data = transaction.args.slice(0, mLength); // fix the data var hs = transaction.args[mLength], scope = transaction.args[mLength + 1]; // fix the callback [duplicate code] transaction.cb = scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs; } } return true; } // -</Ext.Direct .NET Upgrades> ---------------------------Last edited by codeable; 18 Mar 2010 at 11:54 AM. Reason: Adding Comment
-
18 Mar 2010 12:13 PM #142
Exceptions
Exceptions
The only other thing I found while ensuring the architecture fits my needs, was the exception handling in the request. I require a bit more info about exceptions so I can handle them on the client side. I have adjusted two basic bits:
1) Added support for InnerException to DirectException.
------------------------------------------------------
Providing the inner exception allows the ability to send the exception to the client. Where it can be processed with some intelligence.
a) Add support for InnerException
b) Add support for sending the error type to the clientCode:public class DirectException : ApplicationException { ... public DirectException(string msg, Exception innerException) : base(msg, innerException) { } ... }
c) Pass along the inner exception to the clientCode:internal class DirectResponse { ... [JsonProperty(PropertyName = "implementationexceptiontype")] public string ImplementationExceptionType { get; set; } ... }
2) Skipping over any TargetInvocationExceptions thrown.Code:// DirectProcessor.ProcessRequest() private static DirectResponse ProcessRequest(DirectProvider provider, DirectRequest request) { DirectResponse r = new DirectResponse(request); try { r.Result = provider.Execute(request); } catch (DirectException ex) { r.ExceptionMessage = ex.Message; r.Type = DirectResponse.ResponseExceptionType; if(ex.InnerException != null) { r.ImplementationExceptionType = ex.InnerException.GetType().ToString(); //TODO: convert to JS object } } return r; }
-------------------------------
Since all exceptions raised in client code will result in the target exception, I decided to simply ignore it and pass the actual exception raised.
Code:// DirectProvider.Execute() internal object Execute(DirectRequest request) { ... try { ... } catch (TargetInvocationException tex) { throw new DirectException("Error occurred while calling Direct method: " + tex.InnerException.Message, tex.InnerException); } catch (Exception ex) { throw new DirectException("Error occurred while calling Direct method: " + ex.Message, ex); }
-
18 Mar 2010 4:28 PM #143
I definitely think it would be a good idea to be able to attach certain metadata to calls (like a user id). However I'd prefer to wait until later, Direct will be having some work done on it for the 4.0 release, so I'll keep your suggestions in mind for then.
Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
-
18 Mar 2010 7:34 PM #144
Sounds good to me. I'll just upgrade this version for now and await 4.0!
-
19 Mar 2010 3:29 PM #145
I've implemented my ideas! The only thing the client-side needs to do is provide an acquireMetaData method. Full client side would be:
The Server side of things has two Attributes: DirectMetaParameter and DirectMetaParameterIgnore. With these two attributes you can define the metadata on the Action level or Method level as these examples will demonstrate.Code:// -<Consumer Specifics> --------------------------- function acquirePageIdentifier(action, method) { return pageIdentifier; } Saturn.Remote.UserHandler.acquireMetaData = acquirePageIdentifier; // -</Consumer Specifics> --------------------------- Ext.Direct.addProvider(Saturn.Remote.UserHandler);
Implicit parameter called pageContextID
Or the same implicit parameter at the Action level (will add to all DirectMethods)Code:// C# [DirectMethod, DirectMetaParameter("pageContextID")] public string GetImplicitMetaParameter() { // simply returns the provided metaparameter object pageContextID = base.GetMetaParameter("GetImplicitMetaParameter", "pageContextID"); return pageContextID.ToString(); } // JS Saturn.User.GetImplicitMetaParameter(function(data, trans) { // handle results });
You can use the ignore to skip a method when the class level attribute is usedCode:[DirectAction("User"), DirectMetaParameter("pageContextID", false)] public classUserHandler : DirectHandler { [DirectMethod] public string GetImplicitMetaParameter() { // simply returns the provided metaparameter object pageID = base.GetMetaParameter("GetImplicitMetaParameter", "pageContextID"); return pageID.ToString(); } }
You can also explicitly provide the metadata parameter like so:Code:[DirectAction("User"), DirectMetaParameter("pageContextID", false)] public classUserHandler : DirectHandler { [DirectMethod, DirectMetaParameterIgnore("pageContextID")] public string GetImplicitMetaParameter() { // there is no pageContextID Available here. } }
Anyhow, just thought I'd share my excitement.Code:[DirectMethod, DirectMetaParameter("pageContextID", true)] public string GetImplicitMetaParameter(object pageContextID) { // the provided value is overwritten based on the attribute "overwrite" option return pageContextID.ToString(); }
-
23 Mar 2010 2:26 AM #146
Just a quick note: This implementation doesn't compile out of the Box
with the latest RC of the JSON.NET Lib (3.5.6 RC 6 http://json.codeplex.com/releases/view/37810),
but it's pretty easy to fix (just expanding the Parameter Lists of a few methods).
Going to give it a try now and thanks for your work evant :-)
-
23 Mar 2010 4:03 AM #147
Ahh yeh I tried that but didn't yet fix it. Thanks for the heads up.
-
23 Mar 2010 4:40 AM #148
No Problemo. BTW Fixing the Compile Errors ain't enough, the Newtonsoft Lib must have changed quite a bit compared to the one that's included in the Download. Not even the Echo sample works with the new Lib...
Don't have too much time to investigate that tough and will stick with the provided binary for now. But it would be super sweet to have this fixed...
-
23 Mar 2010 5:04 AM #149
Or if there's no time to fix it (i think evant might be a really busy guy) he could tell us which one of the 6 "3.5" Beta-Versions from Codeplex he was using when creating the Router. The shipped assembly says only "3.5" as Version for the Router.
Don't want to be bitchy, it's just that i like to compile everything from source if i can...
-
23 Mar 2010 5:32 AM #150
I can easily update it, but it's only a couple of weeks old. I wonder what changed.
I'll check it out tomorrow.Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!


Reply With Quote