Work, a new house, young daughter, and watching Dexter from the beginning doesn’t leave a lot of time for writing a software blog. Fortunately, tonight I finished the last episode (terrible ending) and it’s time to get back to writing!
To catch you up to the current season in my storyline; I’ve been working in the enterprise world, the land of three letter acronyms (TLA). I recently asked a few of my co-workers to help me come up with a short list to capture the type of work we’ve been doing, here’s what we came up with:
|
|
In addition to all of the TLA’s, we’ve been working with a ton of new (and old) technology which is something that I thought I would post about. What’s interesting about working with many of these ERP-related systems is that if they are not SAP or Oracle, they don’t seem to get a lot of exposure. This makes working on these systems so much harder because information is no longer a Google (or Bing) search away. Not only is the technology older, but the way to access information about the technology is a throw-back to the days of (gasp) reading manuals and asking real people.
The particular ERP system we use is called QAD, which uses a web service based interface called Qxtend to communicate to other systems. Trust me, more than once I tried searching for interfacing with QAD via Qxtend and .NET, but to no avail. Working with Qxtend as a .NET developer is extremely different than consuming typical web services, at least for us at this stage in our understanding. Instead of adding a service reference or using WCF or similar framework, we had to do this an older more manual way which I will outline below. It does seem to work quite reliably, but there were several gotcha’s both in setting up the Query Service on the part of Qxtend and consuming it from .NET. All code on the .NET side can be used to connect to other SOAP based web services, so if you aren’t using QAD, don’t worry – you can still get a bit out of this code.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Net; using System.Xml; namespace QxtendSoapCall { class Program { static void Main(string[] args) { //Prep information related to Qxtend //(these values are made up for demo purposes) string url = "http://qad-qxtend/services/QDocWebService"; string receiver = "qad_rcv"; string domain = "abc"; string version = "v1_1"; string sourceApp = "abc"; string profile = "GetCustomerReps"; int maxRows = 0; //unlimited //Set filter for query service (optional) //(these values are made up for demo purposes) string part = "ABC-123"; string filter = string.Format("pt_part = {0}", part); //Load generic xml request template from external file //(create an empty QueryService QDOC request to begin and add placeholders) string templatePath = @"C:\XmlData\QueryService.xml"; string requestXML = string.Empty; using (StreamReader streamReader = new StreamReader(templatePath)) { requestXML = streamReader.ReadToEnd(); } //Replace template values with values for this query service requestXML = requestXML.Replace("{receiver}", receiver); requestXML = requestXML.Replace("{domain}", domain); requestXML = requestXML.Replace("{version}", version); requestXML = requestXML.Replace("{sourceApplication}", sourceApp); requestXML = requestXML.Replace("{profile}", profile); requestXML = requestXML.Replace("{filter}", filter); requestXML = requestXML.Replace("{maxRows}", maxRows.ToString()); //Clean up template requestXML = requestXML.Replace("\n", "").Replace("\r", ""); //Prep service call variables for qxtend WebRequest request = null; WebResponse response = null; string xmlResponse = string.Empty; try { //Prepare web request request = WebRequest.Create(url) as HttpWebRequest; request.Method = "POST"; //post method request.ContentType = "text/xml"; //xml request.Headers.Add("soapaction", url); //soapaction header request.Headers.Add("Synchronous", "Yes"); //synchronous request.Timeout = 30000; //30 seconds timeout expiry //Encode xml string into byte array byte[] byteData = Encoding.UTF8.GetBytes(requestXML); request.ContentLength = byteData.Length; //Post byte array using (Stream postStream = request.GetRequestStream()) { postStream.Write(byteData, 0, byteData.Length); postStream.Close(); } //Get web response response = request.GetResponse() as HttpWebResponse; //Pull response into stream Stream stream = response.GetResponseStream(); //Read stream StreamReader reader = new StreamReader(stream); xmlResponse = reader.ReadToEnd(); } catch (WebException webEx) { //TODO: Handle your web exceptions here } catch (Exception ex) { //TODO: Handle your general exceptions here } //Convert string to XmlDocument (or XDocument) XmlDocument xdoc = new XmlDocument(); if (!string.IsNullOrEmpty(xmlResponse)) { xdoc.LoadXml(xmlResponse); } //TODO: Do something with XML now that you have data from QAD } } }
That’s it, now you’ve got a way to generically call QAD Qxtend Query Service from .NET without needing an XSD or creating service references to .NET. This is fairly new for me, so if you see any bugs or better approaches, please leave a comment!