Is it possible to create a new PayPal.Payments.DataObjects.TransactionResponse?
I'm currently working on upgrading (our old ERP system) to TLS 1.2, and I need to override a function that returns a PayPal.Payments.DataObjects.TransactionResponse, but PayPal.Payments.Communication.PayflowNETAPI.SubmitTransaction returns a string. Trying to simply create a new PayPal.Payments.DataObjects.TransactionResponse hasn't worked - I'm told in the VB code that:
'PayPal.Payments.DataObjects.TransactionResponse.Private Sub New()' is not accessible in this context because it is 'private'.
Trying in the C# code yields a less descriptive error:
'TransactionResponse' does not contain a constructor that takes 0 arguments
(replacing the 0 with any number of arguments that you put in -- I tried up to 8 or 9)
I am open to solutions in either VisualBasic or C#. Although the function in question is in VB, we opted to send our transactions to an internal processing server, which will return the string (written in C#), so I can do this from either side.
Basically, I just need to take the response (currently in string format), probably parse it (although a straight string conversion would be fine too), and put the info into a PayPal.Payments.DataObjects.TransactionResponse.
You have source code here.
You can check which parameter send to the constructor.
From a quick read of the Paypal SDK code mentioned by Ygalbel, it looks like there is no new() function. Rather, you would declare your var of type PayPal.Payments.DataObjects.TransactionResponse and then use the set and get accessors to set/get data in the class.
Related
Can someone give me an example of the use of the RunCommand method that takes a string argument only (called CommandName) available in the MongoDB .NET driver? I know there is an overloaded RunCommand method that takes an object reference (I think a CommandDocument object) as an argument, but I'd rather not use that one.
I'm having trouble getting the syntax right for CommandName. Thanks in advance!
If you are using some recent version of the official C# driver, the "real" string based version you are referring to (CommandResult RunCommand(string commandName)) is only part of the legacy driver component (check the namespace). I would hence not recommend using it.
The "official" interface currently looks like this:
TResult RunCommand<TResult>(Command<TResult> command, /* and some additional optional parameters */)
And since the C# driver heavily relies on implicit type conversions, there also is one from a string (and a BsonDocument) to the corresponding sub types of Command<TResult> (JsonCommand<TResult> and BsonDocumentCommand<TResult>). So you can effectively pass a string to the above new RunCommand() method, too.
You can therefore write either one of the following lines both of which do the exact same thing:
RunCommand<BsonDocument>("{count: \"collection_name\"}")
RunCommand<BsonDocument>(new BsonDocument("count", "collection_name"))
I have a huge code base and I recently made a change where I changed the type of a parameter from String to a custom class. On the next compile I got all the areas where the impact was, but areas where the input type was of type Object failed. for e.g.
String str = "32"
int i = Convert.ToInt32(str)
Now I have changed String to a new custom type lets say MyCustomClass I would now want following code to fail on next compile
MyCustomClass str = new MyCustomClass("32")
int i = Convert.ToInt32(str)
but it won't as Convert.ToInt32 also accepts type Object. Is there some way I can make a change in MyCustomClass that it's not considered Object anymore.
Please note: Convert.ToInt32 is only used for sample I have many more such functions, so please focus your suggestion/answer to question asked.
Override ToString() and IConvertible
You said in the comments that your intentions are to find places where your object, which had previously been treated as a string, and are now being treated as an object.
In these situations typically, the third-party code would call .ToString() on your object to get something which it can use.
So, Convert.ToInt32(str) is equivalent to Convert.ToInt32(str.ToString()).
If you implement ToString() and IConvertible to return whatever your old version of str looked like then it should continue to work in the same way as the old version.
Probably.
Sorry I know that is not the 100% perfect compile time answer you were looking for, but I think you also know very well that your MyCustomClass will always be considered object.
Possible compile time answer:
Write a tool which uses reflection to iterate over every class/struct/interface in every system/third-party DLL.
Output a load of CS files which contain all these same classes, but just throw NotImplementedException.
(T4 could help you do this)
Compile these classes into dummy.dll
Your .csproj now references only this one dummy.dll, instead of the real dlls.
Your project should compile fine against the dummy dll.
Look at your dummy.cs files and delete any use of object.
Re-compile... and suddenly you get a load of compile time errors showing you anywhere you are using an object.
Impliment an implicit cast from MyCustomClass to String.
public static implicit operator string(MyCustomClass str)
{
return "Legacy respresentation of str";
}
This allows the complier the choice of choosing ToInt32(Object) or ToInt32(String), and I bet it favours the later.
This way all your existing function calls will remain the same so you wont have to be concerned about third party implentation details.
(Sorry, I am not at a computer right now so I can`t test that my assumtion is correct. If you do test this, be sure to consider extension methods, as they can affect the conpilers desision making in unexpected ways)
First, my apologies. This post might be a bit too vague. I have a problem I cannot reproduce in a small sample code section. Here is what I do:
F# application uses a C# DOM, generated from an XML Schema (xsd.exe).
The instance of the DOM is created in C# and returned to F# application from a function call.
The instance (here named type is 'X') is stored into a f# record like this:
type Something = { Dom : X option }
Later in the code I have something like this:
match myRecord.Dom with
| Some(dom) -> CSharpCode.Save( dom, filepath ) // error: Type 'X' not compatible with type 'X'
So basically, I get the Dom instance from C# and pass it back. In the last line above, I get the error message mentioned in the title: Type 'X' is not compatible with type 'X'.
I have no idea what I should look for as in my simple sample program where I try to reproduce this, I never run into this error. Any ideas?
Looking at this troubleshooting page, the phrase 'not compatible with type' seems to be used in the context of numerical values, rather than general type matching.
Another guess is that your code sample has CSharpCode.Save( dom, filepath ), but in F# function arguments are whitespace-separated rather than comma-separated, so I would have expected CSharpCode.Save dom filepath. Wouldn't your sample be constructing a tuple of dom, filepath and attempting to pass it to .Save?
Basically, when I call DeleteUrlCacheEntry (which is part of the Wininet.dll API) I either get returned the number 1 (which means, deletion successful) or the number 0 (which meant, deletion didn't work).
My question is, how can I find out why a deletion did not work? (that is, when a 0 is returned). I heard there is a GetLastError() function in C++, however I am using VB6 and apparently the GetLastError equivalent in VB6 is the Err.LastDllError property.
After a DeleteUrlCacheEntry attempted deletion fails (returns 0) I call/query the Err.LastDllError and it always returns 0 - no matter what. It returns 0 even if DeleteUrlCacheEntry returns 0 (deletion didn't work) and even when it returns 1 (deletion did work). I also make the call/query to Err.LastDllError as soon as possible (as in, right after the DeleteUrlCacheEntry call).
I am really confused, because I don't even get a runtime error or any typical exception (or any exception for that matter). I do not have On Error Resume Next to ignore exception anywhere in my application, so every means of an error being reported to me is available but I cannot for the life of me figure out why a particular DeleteUrlCacheEntry() attempt will fail and return 0 (there doesn't seem to be a way for me to find out).
So, my question is, how do I get extended error information from the DeleteUrlCacheEntry() function (residing in the wininet.dll API)?
If you would like more information on the reason why I am looking for extended error information from the DeleteUrlCacheEntry() function, I have another question which details this (together with actual examples of cache items that work and don't work when a deletion is attempted): https://stackoverflow.com/questions/12096546/deleteurlcacheentry-function-of-wininet-api-not-deleting-some-internet-explo
Also, just to add, I am using VB6 - but principally it should be the same across most languages as it is an API call. Here is my declaration in VB6:
Public Declare Function DeleteUrlCacheEntry Lib "WININET" Alias
"DeleteUrlCacheEntryA" (ByVal lpszUrlName As String) As Long
Also, I am calling it like this:
Dim lReturnValue As Long
Dim cacheFileString As String
' GetStrFromPtrA turns Pointer (Long) to String. cacheFileString is the actual text/string of the lpszSourceUrlName turned from Pointer (Long) to String (human readable cache file name/string). Also, cacheFileString is retreived from FindFirst/NextEntry functions in a loop, so can't be incorrectly formatted or anything, as it also works when deleting most other items.
cacheFileString = GetStrFromPtrA(icei.lpszSourceUrlName)
lReturnValue = DeleteUrlCacheEntry(cacheFileString)
The lReturnValue ends up being 0 if deletion didn't work, and 1 when deletion does work, and that is it. Also, Err.LastDllError always returns 0.
Thank you for your anticipated assistance.
Personally I would set a break point on the call to DeleteUrlCacheEntry(), and step through it observing what the values in the call stack are.
Other than that, there is not much that can be said without a code snippet.
If Err.LastDllError is returning 0 than either GetLastError() really is returning 0, which is unlikely, or VB is not calling GetLastError(), which is more likely. Such as if the VB declaration of DeleteUrlCacheEntry() is wrong, like it is not setting the DllImport.SetLastError property to true under .NET PInvoke.
This might not be directly relevant, but it seems to me that you are doing an unecessary string copy here. Why not directly use the string pointer you already have:
Public Declare Function DeleteUrlCacheEntry Lib "WININET" Alias "DeleteUrlCacheEntryA" (ByVal lpszUrlName As Long) As Long
Dim lReturnValue As Long
lReturnValue = DeleteUrlCacheEntry(icei.lpszSourceUrlName)
(This is assuming that icei.lpszSourceUrlName is a pointer to an ANSI string.)
Also, you do realise that Err.LastDllError is overwritten everytime a command called via a VB declare or type library declare with usesgetlasterror = true? So, for instance, if I declared APIFunc1() and APIFunc2(), and then called them like this;
nRet = APIFunc1(APIFunc2)
... then LastDllError would reflect only APIFunc1().
It's a bit dated ... but I am interested by the subject, so I thought I would share my limited knowledge.
For me, when I called DeleteUrlCacheEntry with a wrong URL, I get an error and Err.LastDllError is set to 2 !
I was searching for a way to insert an ellipsis in a C# path, and found an answer here on stackoverflow: C# Path Ellipsis without Win32 API call
Using the RTM versions of VS2010 and .Net 4.0, I was unable to get the suggested method to work. I searched the 'Net and found example code that uses the same method, but it failed in the same way.
You can see the string I'm trying to shorten in my code below.
After calling the MeasureText method, both the input string (OriginalName) and the output string (ellipsisedName) look like this:
d:\abcd\efgh\ijkl\mnop\qrst\...\test.txt\0F\GHIJ\KLMN\OPQR\STIV\WXYZ\test.txt
Two problems:
1) The resulting string is narfed (the path is truncated as expected, but is followed by what looks like a C-style terminating null and a chunk of the original path).
2) My original string is changed to be identical to the output string.
Am I doing something wrong?
namespace WindowsFormsApplication2 {
public partial class Form1 : Form {
public Form1()
{
InitializeComponent();
string OriginalPath = #"d:\abcd\efgh\ijkl\mnop\qrst\uvwx\yzAB\CDEF\GHIJ\KLMN\OPQR\STIV\WXYZ\test.txt";
string ellipsisedPath = OriginalPath;
Size proposedSize = new Size(label1.Width, label1.Height);
TextRenderer.MeasureText(ellipsisedPath, label1.Font, proposedSize, TextFormatFlags.ModifyString | TextFormatFlags.PathEllipsis);
}
}
}
Holy moly, you've found a whopper of a bug. The P/Invoke used inside the TextRenderer class that calls DrawTextEx() is borked. That API function is writing back into the string, which it is allowed to do since the cchText argument is a LPTSTR, not a LPCTSTR. That destroys the .NET string content for both variables because the string is interned.
The bug isn't specific to .NET 4.0, I see it wrong in the ReferenceSource for .NET 3.5 SP1 as well and can repro it on VS2008. The trouble is in the internal WindowsGraphics.MeasureText function. You can report the bug at connect.microsoft.com.
A possible workaround is to alter the string so it gets copied and can't affect the original:
string ellipsisedPath = OriginalPath + '\0';
But the better workaround in this case is to simply not pass the ModifyString option, it serves no purpose. Which is safer too, there is still a possibility of destroying the garbage collected heap with the first workaround. The fix for Microsoft is similarly simple, it should just mask out the ModifyString option. It is documented to have no effect.
My original string is changed to be identical to the output string.
You've asked for this to happen by specifying TextFormatFlags.ModifyString, which the docs say
Modifies the specified string to match the displayed text. This value has no effect unless EndEllipsis or PathEllipsis is also specified.
This is (to my mind) an unusual way for a .NET Framework call to operate, but it does clearly say it will do this. Both the 'original' string and the 'output' string end up being modified, because string is a reference type (though usually with immutable value semantics) - when you say
string ellipsisedPath = OriginalPath;
you are actually just making ellipsisedPath refer to the same string instance as OriginalPath does. When this instance gets modified by the API call, both the references to it will see the modification.
As for
the path is truncated as expected, but is followed by what looks like a C-style terminating null and a chunk of the original path
my guess would be that the abstraction this managed wrapper provides around the Win32 API call is being somewhat leaky, as abstractions are prone to being - it's not shielding you from the fact that the underlying call works with C-style strings. It might be that you'll have to deal with yourself.