Hi Rick,
I just upgraded from from Webconnection 7.32 to 7.40 and replaced the newtonsoft.json.dll and wwdotnetbridge.dll in my project folder for an existing project that was created with version 7.32.
Code that worked in 7.32 no longer works in 7.40.
Here is the code that now no longer extracts this.given_name at the end of this code snippet. Wondering how to make this work?
FUNCTION dotnetJWTdecode(lctoken)
do wwDotNetBridge
LOCAL loBridge as wwDotNetBridge
loBridge = GetwwDotnetBridge()
loBridge.LoadAssembly("..\bin\Debug\net472\System.IdentityModel.Tokens.Jwt.dll")
loInstance = loBridge.CreateInstance("System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler")
loResult = loBridge.Invokemethod(loInstance, "ReadToken",lcToken)
lopayload = loBridge.GetProperty(loResult,"PayLoad")
loResult = loBridge.CreateComValue()
loResult.Value = ""
loBridge.InvokeMethod(loPayLoad,"TryGetValue","given_name",@loResult)
this.given_name = loResult.Value
Thanks Greg

Peanut gallery here. Silly question time, did you recompile your code with the 7.40 wconnect.h
file? As well as make sure you have the matching external DLLs?
Hmmm... this is a by ref operation. There were some changes related to this, so it's possible something broke here. I have to check.
Let me get back to you...
+++ Rick ---
In the meantime, can you just retrieve given_name
directly via GetProperty()
?
+++ Rick ---

Are you sure that code worked before? It shouldn't have - not if you're using the InvokeMethod()
. It works if you're directly calling the COM method (ie. no InvokeMethod()
call) but when you use InvokeMethod()
the indirect calling loses the variable scope through the abstraction. It's possible to do but you have to use ComValue
to wrap the by ref parameter.
The documentation has pointed out how this works for some time:
Here's a sample (added to the wwDotnetBridgeSamples as PassByReference.prg
now) that demonstrates what works and what doesn't:
your use case is the third example with ComValue
I think
CLEAR
LOCAL loNet as Westwind.WebConnection.TypePassingTests
do wwDotNetBridge
LOCAL loBridge as wwDotNetBridge
loBridge = GetwwDotnetBridge()
loNet = loBridge.Createinstance("Westwind.WebConnection.TypePassingTests")
lnInt = 10
lnDecimal = 5.22
lcString = "Hello World."
? "--- Original Values"
? TRANSFORM(lnInt) + " " + TRANSFORM(lnDecimal) + " " + lcString
?
? "--- WORKS: Direct calls can use @ ref syntax"
?
loNet.PassByReference(@lnInt,@lcString,@lnDecimal)
? lnInt,lnDecimal,lcString
?
? "--- THIS DOES NOT WORK - InvokeMethod cannot use @ ref syntax"
?
*** THIS DOES NOT WORK!
loNet = loBridge.Createinstance("Westwind.WebConnection.TypePassingTests")
lnInt = 10
lnDecimal = 5.22
lcString = "Hello World."
loBridge.InvokeMethod(loNet,"PassByReference",@lnInt,@lcString,CAST(lnDecimal as Currency))
? lnInt,lnDecimal,lcString
?
? "--- WORKS: InvokeMethod can use ComValue to pass by Ref/Out parameters"
?
*** THIS WORKS - - InvokeMethod cannot use @ ref syntax, use ComValue instead
loInt = loBridge.CreateComValue(10)
loString = loBridge.CreateComValue("Hello World")
loDecimal = loBridge.CreateComValue()
loDecimal.SetDecimal(5.22)
loBridge.InvokeMethod(loNet,"PassByReference",loInt, loString, loDecimal)
? loInt.Value
? loString.Value
? loDecimal.Value
?
? [--- Enum.Parse("9", out int result) - static invokemethod using ComValue]
?
*** Out parameter
loResult = loBridge.CreateComValue(0)
? loBridge.InvokeStaticMethod("System.Int32","TryParse","9", loResult)
? loBridge.cErroRMSG
? loResult.Value
?
?[--- Arrays have to be passed as ComArrarys to update]
*** Array out by reference
loNet = loBridge.Createinstance("Westwind.WebConnection.TypePassingTests")
loStrings = loBridge.CreateArray("System.String")
loStrings.AddItem("It's")
loStrings.AddItem("BigDay")
? TRANSFORM(loStrings.Count) + " strings to start..."
loValue = loBridge.CreateComValue(loStrings)
*** Adds items to the array and sets a new array by reference
lobridge.InvokeMethod(loNet,"PassArrayByReference",loValue)
loStringsResult = loValue.GetValue()
*loBridge.GetProperty(loValue,"Value")
? TRANSFORM(loStringsResult.Count) + " strings after method"
FOR lnX = 0 TO loStringsResult.Count -1
? loStringsResult.Item(lnX)
ENDFOR
You can run this yourself to verify that this works - the TypePassingTests class is compiled into wwDotnetBridge.dll
.
In your case I wonder if you were using the direct call before. That should work but the .NET version may have changed with generic overloads and that may be breaking the direct call.
+++ Rick ---
Hi Rick,
I tried the 3rd example you suggested but had no success.
The weird thing is the code worked as shown in 7.32. I tried in 7.40 with old as well as the new version of wwDotNetBridge.dll and neither the old or new version of the wwDotNetBridge.dll works in the 7.40 upgrade? That seems to point towards it not being the wwDotNetBridge.dll but instead maybe the internal foxpro code that handles the wwDotNetBridge.dll or am missing something?
Thanks Greg
Not sure about 7.x
- latest release is 8.1
and as I mentioned there were fixes in the 8.0 update that addressed by ref parameters.
I'm not sure how @ syntax could have ever worked with InvokeMethod()
- it will work with direct calls though. You should be able to call TryGetValue()
directly (unless the class is generic or there are several overloads in the method).
+++ Rick ---
Come to think of it - sometime back I changed how methods are executed by retrieving the actual member instance and invoking rather than going through the higher level (and much slower) APIs - those higher level APIs are more COM like and support additional features that are not available. I think in that process we probably lost the ability to pass through @ parameters. There were other related changes so even if we were to go back to that it likely wouldn't work as parameters are passed through multiple levels and both parameters and result values are potentially fixed up to work with types that FoxPro doesn't natively support.
So the ComValue
approach for reference parameters is the recommended approach as that works reliably in a way that our code can control in all situations.
I think the original code for this change (probably 7.3x+
and later) had a bug and that's what you're likely running into, where in some cases the parameters are not updating.
You can give this a try with the OSS version which is up to date, or with the latest West Wind Client Tools and Web Connection (v8.1) - all of which have the fix using ComValue
(or ComArray
for collections).
+++ Rick ---
Hi Rick,
That makes more sense. For now I'll just revert back to the 7.32 version as it works fine as is. In the near future I'll upgrade to the latest 8.1.x version.
Thanks,
Greg