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 ---