A few weeks ago, I began working on a piece of software that I conceived of more than 4 years ago. In a nutshell, the application is designed to match documents that are similar (if not identical) in content to a source document. I envisioned that this application could be used in many ways, for example by media companies to ensure that author submissions are not plagiarized or by educators to make sure that student papers are original works.
It did not take long to get my initial application prototype written — when you mull over a project for almost 4 years, it should go pretty smoothly when you start. However, as I neared the completion of my initial prototype phase, I remembered OpenAmplify — a product I had recently reviewed for TechRepublic — and realized that it could add a lot of value to my project. Also, from what I learned when reviewing OpenAmplify, I knew that the integration would be fairly easy.
In an ironic twist, it's actually more effort to get the simple OpenAmplify Web service working in .NET than something much more complex. This is because the OpenAmplify Web service requires an HTTP GET or POST, while .NET environment are geared towards the SOAP system.
Indeed, if OpenAmplify used SOAP and provided a WSDL I could point to, I would not need to lift a finger for the basic integration. On the other hand, I have a lot more flexibility working with OpenAmplify without being restricted to what is being exposed via SOAP, and the code needed is pretty easy to write, so it's not a bad thing.
For my project, I will push entire documents to OpenAmplify, so I decided that it would be better to use an HTTP POST rather than a GET. The .NET Framework does not make it nearly as trivial to put data to a host via POST as you might expect.
Initially, I thought I wanted to get my results as an XmlDocument object, but then I changed my mind. Why not use XDocument and so I get to use LINQ on my results? You will see in the upcoming articles how this decision paid dividends, as LINQ allows me to slice ‘n dice the OpenAmplify data with ease.
Here's an example of my completed code:
private XDocument GetOpenAmplifyResults(string openAmplifyInput, string openAmplifyAmpId)
var postData = "apiKey=" + HttpUtility.UrlEncode(openAmplifyAmpId) + "&inputText=" + HttpUtility.UrlEncode(openAmplifyInput);
var postBytes = Encoding.UTF8.GetBytes(postData);
var request = System.Net.WebRequest.Create("http://portaltnx.openamplify.com/AmplifyWeb_v11/AmplifyThis");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postBytes.Length;
var dataStream = request.GetRequestStream();
dataStream.Write(postBytes, 0, postBytes.Length);
var response = request.GetResponse();
var openAmplifyXml = new XmlDocument();
var result = XDocument.Load(new XmlNodeReader(openAmplifyXml));
Let's take a look at what's happening under the hood —
Up front, I need two pieces of information to run the process: the text to pass to OpenAmplify (the openAmplifyInput parameter) and the OpenAmplify API key (get yours here), also as a parameter. The next thing I needed was to construct the POST data. Like the data sent to a browser via the query string in an URL, the POST data parameters are separated by ampersands, with name/value pairs, but what about ampersands in the data itself, or other special characters? I needed to URL Encode them.
As you can see, I use the HttpUtility.UrlEncode() method on the data itself, while concatenating my name/value pairs into a single string, postData. The next thing I did was to transform the data into an array of bytes representing the UTF8 encoded data. This made it suitable for processing by a Web server, and included in the Web request. Next, I created a WebRequest object, passing to it the OpenAmplify service URL (http://portaltnx.openamplify.com/AmplifyWeb_v11/AmplifyThis). After I created the WebRequest object, I set some properties:
- .Method set to "POST"
- .ContentType set to "application/x-www-form-urlencoded"
- .ContentLength set to the number of bytes in the post data (postBytes.Length)
Next, I provided the data, by opening the request's data stream direction, and writing the byte array to it, then closing the data stream. After all of this is done, I am ready to make the request.
When I call the GetResponse() method of the request, that triggers sending the data and giving the response from the OpenAmplify server. You will see that what I do with this response is to create an XmlDocument from the response's data stream, and close the response out.
Do not forget to close the response object, otherwise you are just leaving it dangling, and it could be a while before it's freed, which is bad for the client system and bad for the OpenAmplify server. Finally, I convert the XmlDocument to an XDocument, which again, lets me go nuts with LINQ on the OpenAmplify data.
This example uses all of the defaults for OpenAmplify. To customize it for your needs check out the documentation to get an idea of how you can narrow down your request.
As you can see, this small amount of code unleashes huge potential. I can now combine OpenAmplify's results with LINQ's ability to manipulate, transform, and query XML. In my next article I will easily compare the author demographics and style portions of the OpenAmplify results with only a few lines of LINQ code.
If you have any questions, suggestions, and so on, please let me know.
Justin James is the Lead Architect for Conigent.