Using a third party web service in vb.net - asp.net

I am trying to build an app in VS Pro 2012 (VB.NET) that will invoke RoyalMail's MailMark WSDL which has methods such as RetrieveActiveSupplyChains which are expecting a single parameter (request).
I have used svcutil with the /l:vb switch to download the WSDL and referenced it in my project and I can see methods being exposed once I have done
Dim client As PosterUploadClient = New PosterUploadClient()
Now typing client. brings up all the methods I expect to see and I can pass authentication and see the state change when I do client.open() but what I can't figure out is how to provide the parameters the actual methods need. According to their documentation, RetrieveActiveSupplyChains doesn't need a parameter but they have provided an xml example of the request structure so my assumption is that I'd need to construct this as xml with the appropriate values and send it as "request"?
Does this sound right? I know this is probably meat and veg for a web programmer but not something I have attempted before. The xml they supplied as an example looks like the below:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://rm-manifest.com/2014/01/service/IPosterUpload/RetrieveAllActiveSupplyChains</a:Action>
<a:MessageID>urn:uuid:ab5e32a3-812e-4d91-97a8-de00a08874e9</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://rm-manifest.com/PosterUpload2/PosterUpload.svc/service</a:To>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2014-10-03T14:32:58.480Z</u:Created>
<u:Expires>2014-10-03T14:37:58.480Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-dfaaf0b0-3823-4f75-b607-33f7434295dc-1">
<o:Username>NetworkAccess</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">p1</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<RetrieveAllActiveSupplyChains xmlns="http://rm-manifest.com/2014/01/service">
<request xmlns:b="http://rm-manifest.com/2014/01/messages" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
</RetrieveAllActiveSupplyChains>
</s:Body>
</s:Envelope>
But I'm still not sure how it actually needs to be submitted, certainly if I read that sample one in with a new xmltextreader it doesn't like it with the following error message
Value of type 'System.Xml.XmlTextReader' cannot be converted to 'MM_TEST.Mosaic.EIB.PosterUploadService.Core.Messages.RetrieveActiveSupplyChainsRequest'
My assumption was the WSDL replaces the need to actually create a "New HttpRequest" in my code but not sure. I've done a lot of googling but not getting anything that quite works like this
The WSDL is here if this helps:
https://customertest.rm-manifest.com/PosterUpload/PosterUpload.svc

Just call the method. The provided XML is what is actually sent to the server by the WCF proxy when you call the method. You don't need to use it at all.
If you use a tool like Fiddler, you'll see that simply calling client.RetrieveAllActiveSupplyChains will send an HTTP request with a body similar to the XML sample.
In fact, everything outside the RetrieveAllActiveSupplyChains tag isn't related to the method at all - it's security and addressing data used to establish and execute a connection with a web service in general. All of this is handled by WCF.

Related

How WSSE UsernameToken Id is generated in WCF

I am trying to generate a soap message for a WCF service. The service is using UserNameOverTransport with message security version WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10.
I got the header sample
<o:UsernameToken u:Id="uuid-7f6455d4-42ab-49fa-8b25-35427c00bb7a-1">
<o:Username>xxx#xxx.com</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">yyyyy</o:Password>
</o:UsernameToken>
The client is not going to be in .Net. Can anyone help me in figuring out how the id is generated.
If you ask this question because your authentification is not working, you likely don't need the Id label.
As we can see in this specification from xmlsoap.org website,
4.1. UsernameToken Element
/UsernameToken/#Id
A string label for this security token.
This element is just a label and its goal is just to provide identification to the UsernameToken element (you can name it with "myToken" or something else).

Get All Sales Order from Quick Book via QuickBook WebConnector using asp.net

I am using QuicBook Premier Edition UK , I have a company file open inside QuickBook. Build a sample WebService provided in samples and host in IIS. Added that application in WebConnector by using qwc file in samples.
I understood the callback methods required by WebConnector in soap service.
• authenticate
• clientVersion
• closeConnection
• connectionError
• getLastError
• receiveResponseXML
• sendRequestXML
I have tested web service by using WebConnector by using Update Selected button and it gives response 'OK' . But I am still confused how to get started with soap service , samples include 3 Xml request
CustomerQuery,
InvoiceQuery and
BillQuery .
How I test these request and see the response by using service . Can anyone explain the steps required to get me started with my own request of Get all Sales Order.
Thanks
Here is the screenshot
Here is the Last Output.
Version:
2.0.0.1
Message:
OK
Description:
Via closeConnection(): CloseConnection called to application.
Response received from application = OK
Explanation:
After calling authenticate(...), the Web Connector will call the sendRequestXML(...) method.
The sendRequestXML(...) method is essentially the Web Connector's way of saying "Hey, what do you want me to do?"
You should respond with a qbXML request telling QuickBooks/the Web Connector to do something. For example, if you are trying to get sales orders from QuickBooks, you could respond with a SalesOrderQuery qbXML request, something like this:
<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="8.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<SalesOrderQueryRq requestID="2">
</SalesOrderQueryRq>
</QBXMLMsgsRq>
</QBXML>
The Web Connector will then send that request to QuickBooks, it will be processed, and the Web Connector will then call your receiveResponseXML(...) method.
The receiveResponseXML(...) method is essentially the Web Connector's way of saying "Hey, you told me to do something, I did it, and here's all of the data I got back: ... (big blob of XML from QuickBooks here)".
TLDR:
Return a qbXML request from the sendRequestXML method. A qbXML response will be sent to you in the receiveResponseXML method.
More notes:
Bigger explanation of the Web Connector here: http://www.consolibyte.com/docs/index.php/QuickBooks_Web_Connector_Overview
Lots of qbXML examples here: http://www.consolibyte.com/docs/index.php/Example_qbXML_Requests
Hundreds of pages of documentation in the QuickBooks SDK: https://developer.intuit.com/docs/0250_qb/0020_get_set_up/sdk_downloads

Connecting an ASP.NET application to QuickBooks Online Edition

I am trying to create an ASP.NET page that connects to QuickBooks Online Edition, read a couple of values, and display the results. So far I have downloaded the QuickBooks SDK but I have been unable to find a simple step-by-step example on how to create an asp.net page to connect to QuickBooks Online. The QuickBooks SDK documentation and the SDK itself is very confusing and overwhelming. Anyone know of a simple step by step tutorial on where to get started... or maybe a hint on the very first thing to do.
Yishai's answer is partially correct, but not entirely.
You can have your ASP .NET application log in and issue requests without having to send the user over to the QuickBooks Online log in page if you make sure to set the security preferences correctly when you connect up your application to QuickBooks Online Edition.
During the application registration process/connection process, it will ask you if you want to turn on or off login security with a prompt as below. You must tell it you want to turn off login security if you want to be able to access QuickBooks Online Edition data without forcing the user to log in every time. The prompt is something like:
"Do you want to turn on login security?"
You must select:
"No. Anyone who can log into [Application Name] can use the connection".
Outside of that, Yishai is correct about the process. To re-iterate, in a nutshell:
Register for a QBOE account
Register your integrated application with Intuit's AppReg service
Visit a specific link to tie your AppReg application to your QBOE account (make sure you turn off login security when it asks you!)
Make HTTPS POST requests to Intuit's servers to sign on using the connection ticket Intuit will provide you with
Make HTTPS POST requests to send qbXML requests to Intuit's servers, which you can use to add, modify, delete, and query records within QuickBooks Online Edition.
There is some additional documentation and some example requests on my QuickBooks development and integration wiki, specifically the QuickBooks Online Edition integration page.
I have built a solution that does what you're asking in PHP which adds, modifies, and queries data within QuickBooks Online Edition without requiring the user to log in everytime, and it works like a champ. It pushes and pulls order data between a PHP shopping cart (VirtueMart) and QuickBooks Online Edition. The PHP code is available here:
QuickBooks PHP Framework
As a side note, unless you're very familiar with generating SSL certificates and sending them via HTTPS POSTs, you'll save yourself a whole lot of trouble by using the DESKTOP model of communication, and not the HOSTED model. Just make sure to keep your connection ticket securely encrypted.
Also, Yishai's suggestion to: "One is to programatically hit up their login page and submit the credentials as if you were a user. I'm sure its not "supported" but it would likely work." goes specifically against the security/developer guidelines Intuit and the SDK set forth. If they catch you doing that, they'll ban your application from connecting to QuickBooks.
Here are all the steps I took to get this working. Special thanks to Keith Palmer for his comments, answers, and his website which really helped me get this working.
Register your application at http://appreg.quickbooks.com. This will give you your App ID and Application Name. I used these settings:
Target Application: QBOE
Environment: Production
Application Type: Desktop
(using Desktop made things much easier as far as not needing certificates)
A verification key is sent to your email address which you need to enter on page 2 of this wizard.
Set up your QBOE Connection. Once you finish registering your application in Step 1, you will then have an Application ID. Use this ID in the url below to set up your QBOE Connection:
https://login.quickbooks.com/j/qbn/sdkapp/confirm?serviceid=2004&appid=APP_ID
NOTE: Make sure to replace APP_ID in the above url with the Application ID that was created when you registered your application.
The wizard will take you through the following steps:
Specifying a name for your connection.
Granting Access Rights - I gave All Accounting rights since this was easiest.
Specify Login Security - I turned Login Security Off. This is important since it makes submitting the xml to the QBOE much easier since you do not need to get a session ticket for each user.
You will then be given a Connection Key.
At this point you now have the 3 important pieces of information in order to gain access to your QuickBooks Online Edition (QBOE) account.
Application Name
Application ID
Connection Key
Post the XML to QBOE with the 3 pieces of access information and the actual request into your QBOE database. Here is sample c# code that will post to the QBOE gateway. This will return all customers in your QuickBooks database. Make sure to update the xml below with your Application Name, Application ID, and Connection Key.
string requestUrl = null;
requestUrl = "https://apps.quickbooks.com/j/AppGateway";
HttpWebRequest WebRequestObject = null;
StreamReader sr = null;
HttpWebResponse WebResponseObject = null;
StreamWriter swr = null;
try
{
WebRequestObject = (HttpWebRequest)WebRequest.Create(requestUrl);
WebRequestObject.Method = "POST";
WebRequestObject.ContentType = "application/x-qbxml";
WebRequestObject.AllowAutoRedirect = false;
string post = #"<?xml version=""1.0"" encoding=""utf-8"" ?>
<?qbxml version=""6.0""?>
<QBXML>
<SignonMsgsRq>
<SignonDesktopRq>
<ClientDateTime>%%CLIENT_DATE_TIME%%</ClientDateTime>
<ApplicationLogin>APPLICATION_LOGIN</ApplicationLogin>
<ConnectionTicket>CONNECTION_TICKET</ConnectionTicket>
<Language>English</Language>
<AppID>APP_ID</AppID>
<AppVer>1</AppVer>
</SignonDesktopRq>
</SignonMsgsRq>
<QBXMLMsgsRq onError=""continueOnError"">
<CustomerQueryRq requestID=""2"" />
</QBXMLMsgsRq>
</QBXML>";
post = post.Replace("%%CLIENT_DATE_TIME%%", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"));
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(post);
post = xmlDoc.InnerXml;
WebRequestObject.ContentLength = post.Length;
swr = new StreamWriter(WebRequestObject.GetRequestStream());
swr.Write(post);
swr.Close();
WebResponseObject = (HttpWebResponse)WebRequestObject.GetResponse();
sr = new StreamReader(WebResponseObject.GetResponseStream());
string Results = sr.ReadToEnd();
}
finally
{
try
{
sr.Close();
}
catch
{
}
try
{
WebResponseObject.Close();
WebRequestObject.Abort();
}
catch
{
}
}
Couple things to note:
As pointed out by Keith Palmer the qbxml version needs to be 6.0 (even though the IDN Unified On-Screen Reference shows 7.0)
I needed to include the onError="continueOnError" attribute.
Setting the WebRequestObject.ContentLength property is required.
Content Type needs to be "application/x-qbxml"
And finally I received many "The remote server returned an error: (400) Bad Request." exceptions which were not helpful at all but in the end I was able to trace them to something wrong with the xml. So if you get this exception look to your xml as the source of the problem.
The outline of what you have to do are outlined in Chapter 7 of the QBSDK documentation (at least in the 7.0 version of the SDK that I have). You have to open a test account and get permission to connect to their servers.
Once you have your account setup, the basic authentication procedure consists of redirecting your user to the QuickBooks Online site to log in, and once the user has done that, QuickBooks calls back your application with an HTTPS post with a ticket, which is basically a session handle that you can use for your requests, so that the system knows you are authenticated. When you get that response, you parse it and send your own login request to the system based on what you got back.
Then (if I understood the documentation correctly) you are basically doing Https POSTS of xml files with the QuickBooks requests, and you get XML responses that you have to parse to get the data you want.
I hope that gets you started.
The rest of the SDK is documentation (which you will need to know how to form your requests and parse your responses) and everything else is concerned with how to communicate with the desktop product. The only thing you are going to need from the rest of the documentation is how to do error handling, which is really only important if you are posting data to QuickBooks. If you are just reading, it doesn't matter (either your request works out or it doesn't, you don't need to worry about if you need to retry or if that would result in duplicate data).
EDIT: Given your specific use case I see two options. (You aren't crazy, just not the typical QuickBooks Online scenario).
One is to programatically hit up their login page and submit the credentials as if you were a user. I'm sure its not "supported" but it would likely work.
The other is to cache the results (which you should probably do anyway) and have an admin screen where someone does log into QuickBooks online and update the results every morning or evening or whatever makes sense.
In most small businesses, they are going to opt for the first option, but the second one is going to work more consistently, robustly and actually be supported by Intuit if you have an issue.
This looks pretty close to what you need: www.QuickbooksConnector.com
Wasn't able to download it yet.

BizTalk SOAP port password in binding file

I've inherited a BizTalk 2006 application that uses several SOAP ports to request data from a 3rd party web service. The web service is secured by "basic" authentication - username / password. After making a few enhancements to the application I deployed to an integration test server which has access to the 3rd party web service. The BizTalk app was unable to retrieve the data and I soon realised that I had forgotten to set the username / password on the SOAP send ports. I wanted the make deployment of the BizTalk app as automated as possible because I may not be present when it is deployed to the live server. I opened up the binding file, located the 1st of the problem SOAP send ports and looked for the * that BizTalk uses to replace the password - except that it doesn't! It seems that the password for SOAP ports is set to NULL rather than *, see here for more details:
http://msdn.microsoft.com/en-us/library/aa547319.aspx
I proceeded to update the binding but when I came to test, after importing my amended binding file, I found that I had the same problem as before. I've double checked and can confirm that the correct password is now present in the binding file but, although BizTalk doesn't complain during the import, when I run the app I get the following exception:
Details:"ArgumentNullException: String reference not set to an instance of a String.
Parameter name: s
".
If I then manually amend the password through the BizTalk admin console everything work fine.
Has anyone else had a similar problem with the bindings for a SOAP port - does anyone have a solution?
I've been bit by something like this in the past. The password is either put in as '****'. This is ok. I wouldn't want all of my secrets exported with the binding file. What does get you is when you export the bindings and you leave the password NULL. The Variable Type (vt) attribute on the XML element for the password is set to vt="1" which is the same as NULL. It won't matter what you put in for the password. It may even cause the error you described. I would suggest you include a copy of the binding XML for review.
I've never seen this problem before - I'm doing exactly what you are trying to do and it works perfectly.
I've included the <TransportTypeData> element from one of my BizTalk bindings that works. Hopefully having something to compare against helps.
<TransportTypeData>
<CustomProps>
<AuthenticationScheme vt="8">Basic</AuthenticationScheme>
<AssemblyName vt="8">WebService.ProxyClass, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=xyz</AssemblyName>
<Username vt="8">soapUser</Username>
<UseProxy vt="11">0</UseProxy>
<UseSoap12 vt="11">0</UseSoap12><UsingOrchestration vt="11">0</UsingOrchestration>
<UseSSO vt="11">0</UseSSO>
<Password vt="8">MYPASSWORD</Password>
<ProxyPort vt="3">80</ProxyPort><AssemblyPath
vt="8">C:\ProxyClass\bin\Debug\ProxyClass.dll</AssemblyPath>
<TypeName vt="8">ProxyClass.Webservice.servicesService</TypeName>
<MethodName vt="8">PickupRequest</MethodName>
<UseHandlerSetting vt="11">-1</UseHandlerSetting>
</CustomProps>
</TransportTypeData>

Webservice.wsdl and credentials

So I've got a bit of an issue I'm trying to work through. Perhaps some Flex guru could assist?
I have a WebService instance that attempts to load a WSDL file from our JBoss Application Server. If I do something like this:
webService = new WebService();
webService.destination = WebService.DEFAULT_DESTINATION_HTTP;
webService.wsdl = "http://<removed>/services/ApiService?wsdl";
webService.loadWSDL();
everything works fine. The WSDL is loaded successfully and the application can invoke methods against the web service.
The issue is when I need to add some HTTP authentication to the mix:
webService.setCredentials(userName, password);
this line ends up throwing an error stating that credentials are only supported on HTTPS. Ok fair enough, I want to use secure HTTPS anyway!
So then I tried to change it up to this...
webService = new WebService();
webService.destination = WebService.DEFAULT_DESTINATION_HTTPS;
webService.wsdl = "https://<removed>/services/ApiService?wsdl";
webService.setCredentials(userName, password);
webService.loadWSDL();
and now the WebService instance cannot load the WSDL. The error received is:
[FaultEvent fault=[RPC Fault faultString="HTTP request error" faultCode="Server.Error.Request" faultDetail="Unable to load WSDL. If currently online, please verify the URI and/or format of the WSDL (https://<removed>/services/ApiService?wsdl)"] messageId="6905CC5B-5317-C4B3-2D12-84647EE648A7" type="fault" bubbles=false cancelable=true eventPhase=2]
I can reach this URI in the browser just fine and it returns the WSDL as expected.
I am not a Flex guy (learning) but instead a Java developer. I am trying out Flex as a potential client to our system but this has caused me all kinds of grief today. Google doesn't appear to have any quick answers for me and I am a bit stumped.
First question on StackOverflow so hopefully this gets a bite somewhere and helps some other poor Java dev staying late in the office on a Friday night :-)
This seems to be related to your question. We are planning to use https in the future, so I'm curious to know the solution of your problem.

Resources