Several
weeks ago, in my first "Developer Diary" about using OpenAmplify, I
mistakenly thought that OpenAmplify did not have a SOAP interface. Since then,
I've learned that there actually is a SOAP interface to OpenAmplify. Today, I
am going to show you what it takes to work with that interface from Visual
Studio. Please note that I am using VS 2008, and if you are using an older
version of Visual Studio, some of the instructions may be slightly different
when it comes to establishing the initial connection to the service.
The first step in using OpenAmplify via SOAP is to create a
Web Reference to it in your project. To do this, right click "Service
References"in your project, and choose "Add Service Reference".
Enter the http://portaltnx.openamplify.com/AmplifyWeb_v11/wsdl/WSAmplify_v1_1.wsdl
into the URL box in the dialog and com.openamplify.portaltnx in the namespace
field then click the "OK" button. This automatically creates a namespace of
com.openamplify.portaltnx under your project's default namespace, which contains all of the needed classes to make a request to OpenAmplify.
Before you make a request, though, you will need to open the
file app.config to make a few changes. In the file you will see an element called endpoint which has an address attribute. Make sure that the endpoint attribute has this
value in it: http://api.openamplify.com/axis2/services/WSAmplify_v1_1Service
You will also need to take a look at the binding element,
and set the maxBufferSize and maxReceivedMessageSizeattributes to 6553600.
This will ensure that the SOAP client is willing to accept all of OpenAmplify's
output, which can be rather large. Finally, you will need to change the
following timeout values in the binding, since the SOAP service can
occasionally take longer than the default timeouts on very long documents:
-
closeTimeout: 0:10:00
-
openTimeout: 0:10:00
-
receiveTimeout: 0:20:00
-
sendTimeout: 0:10:00
Before you send your text to the SOAP service, you will need
to scrub it first. For one thing, OpenAmplify's SOAP service does not accept
Unicode input, so you will need to convert Unicode to ASCII. Here is the
function I wrote which does the trick:
private string UnicodeToAscii (string input)
{
var asciiEncoder = Encoding.GetEncoding("us-ascii", new EncoderReplacementFallback(string.Empty), new DecoderReplacementFallback(string.Empty));
var encodedBytes = new byte[asciiEncoder.GetByteCount(input)];
asciiEncoder.GetBytes(input, 0, input.Length, encodedBytes, 0);
return asciiEncoder.GetString(encodedBytes);
}
You will also need to strip
out any less-than and greater-than symbols before passing the text along. At
the time of this writing, the service will interpret them as unescaped XML and
not work properly.You are now ready to create a basic request to OpenAmplify.
The code to do this is very simple:
private AmplifyScorecard GetOpenAmplifyResults2(string openAmplifyInput, string apiKey)
{
openAmplifyInput = UnicodeToAscii(openAmplifyInput);
openAmplifyInput = openAmplifyInput.Replace("<", string.Empty);
openAmplifyInput = openAmplifyInput.Replace(">", string.Empty);
var amplifyService = new WSAmplify_v1_1Client();
var amplifyParameters = new List
();
var apiKeyParameter = new Param {Name = "apiKey", Value = apiKey}; amplifyParameters.Add(apiKeyParameter);
AmplifyScorecard results = null;
results = amplifyService.Amplify(openAmplifyInput, amplifyParameters.ToArray());
return results;
}
Of course, you will need to have a using (or Imports
for VB.NET users) statement in your class that refers to the service's
namespace that we created earlier.
There are two things to note here. The first is that I am
declaring my parameters as a List<Param>
object even though the WSAmplify_v1_1Service.Amplify()
method expects an array of Param
objects. This reason for this is that List<T>
is much friendlier to work with, particularly when the number of parameters is
unknown in advance.
The other important item here is that each parameter
consists of a name/value pair (accessed via properties of the same name). The Name property of the parameter should
match the name that you would use when making a POST to OpenAmplify. This means
that, at a minimum, I need to provide the key "apiKey". The
full list can be found here in the documentation.
If you want to perform an OpenAmplify "Search" instead of a
full analysis, you replace the call to the Amplify()
method with a call to the Search()
method. Search() will provide an
AmplifyScorecard object as the
return results just like Amplify()
does.
Once we have the results, what can we do with them? Let's
take a look at the AmplifyScorecard object. It has a number of properties which
correspond to the equivalent results in the XML output:
-
Actions
-
Demographics
-
Styles
-
TopicIntentions
-
Topics
It also adds the property Search
which I will address shortly.
Central to this discussion is the Result class. Result
is a simple class, with only two properties, Name
and Value. Both of these
properties are of type string.
The Name and Valueproperties of Result objects corresponds to the
elements of the same name in the XML output.
Let's take a closer look at these properties, since they are
where the action is. Luckily for us, all of the items at the very bottom of the
object trees (anything of type Result)
correspond perfectly to the XML elements by the same name in the OpenAmplify
documentation.
Actions
Actions is of type ActionScorecard. Within that type there is only one member, TopActions, which is an array of ActionResult objects. ActionResult objects contain the following fields:
-
Action:
Result
-
ActionType:
Result[]
-
Decisiveness:
Result
-
OfferingGuidance:
Result
-
RequestingGuidance:
Result
-
TemporalityResult:
Result[]
Demographics
The Demographics
property has the type DemographicsScorecard
which consists of these properties:
-
Age:
Result
-
Education:
Result
-
Gender:
Result
-
Language:
Result
Styles
Styles like Demographics is very simple. It is a StyleScorecard object with these two
fields:
-
Flamboyance:
Result
-
Slang:
Result
TopicIntentions
TopicIntentions
is of type TopicIntentionScorecard.
This class is fairly complex with the following fields:
-
Domains:
DomainResult[]
-
Domain:
Result
-
Subdomains:
SubdomainResult[]
-
Scores:
Result[]
-
Subdomain:
Result
-
ProperNouns:
TopicIntentionResult[]
-
OfferingGuidance:
Result
-
Polarity:
PolarityResult
-
Max:
Result
- Mean:
Result
- Min:
Result
- RequestingGuidance:
Result
- Topic:
Result
- TopicIntention:
TopicActionTypeResult[]
- ActionType:
Result
-
TopicRoles:
TopicRoleResult[]
-
Decisiveness:
Result
-
OfferingGuidance:
Result
-
RequestingGuidance:
Result
-
TemporalityResult:
Result[]
-
TopicRole:
Result
- TopTopics:
TopicIntentionResult[]
-
OfferingGuidance:
Result
-
Polarity:
PolarityResult
-
Max:
Result
-
Mean:
Result
- Min:
Result
-
RequestingGuidance:
Result
- Topic:
Result
- TopicIntention:
TopicActionTypeResult[]
-
ActionType:
Result
- TopicRoles:
TopicRoleResult[]
-
Decisiveness:
Result
-
OfferingGuidance:
Result
-
RequestingGuidance:
Result
-
TemporalityResult:
Result[]
-
TopicRole:
Result
Topics
Topics is
very similar to TopicIntentions
in complexity. As you may guess by now its type is TopicScorecard made up of these properties:
-
Domains:
DomainResult[]
-
Domain:
Result
-
Subdomains:
SubdomainResult[]
- Scores:
Result[]
- Subdomain:
Result
-
Locations:
Result[]
-
ProperNouns:
TopicResult[]
-
OfferingGuidance:
Result
-
Polarity:
PolarityResult
- Max:
Result
- Mean:
Result
- Min:
Result
-
RequestingGuidance:
Result
-
Topic:
Result
-
TopTopics:
TopicResult[]
-
OfferingGuidance:
Result
-
Polarity:
PolarityResult
- Max:
Result
- Mean:
Result
- Min:
Result
-
RequestingGuidance:
Result
- Topic:
Result
Now let's take a look at using the Search( ) method.
When you use Search( ) you will need to put the terms into the searchterms
parameter in the Param array that gets passed to Search( ). The results that you
receive will still come back as an AmplifyScorecardobject.
Whew! Now, when working with these results it's possible to
use LINQ on the arrays. But on the whole, the "feel" of working with the SOAP
results is a bit different from using the XDocument
results that we got in Part 1 of this series.
Looking back at the Rat Catcher code I don't think that it's
worth going back and switching it over to SOAP at this time, although I am considering it in the future. If I was
using more "clever" LINQ statements leaving it as-is would be the best policy.
In addition, my current strategy has the advantage of allowing me to easily
store the XML for later retrieval, perhaps as a caching system. If I switched
to SOAP I would need to write serialization code of some variety to be able to
stick the results into storage. The tradeoff would be much cleaner code (since
I would not be stepping through the Element
properties of various parent elements) and possibly a slight performance
increase due to eliminating the LINQ overhead.
In Part 5, I will be wrapping up this series with a discussion
of the "business end" of OpenAmplify, in terms of where it fits into Rat Catcher's
overall functionality, my impressions of working with it and how integrating
Rat Catcher with OpenAmplify has influenced Rat Catcher's overall business
model.
Read more from the series:
OA Developer’s Diary – Part 1: Making the Request
OA Developer’s Diary – Part 2: Author Comparisons
OA Developer’s Diary–Part 3: Topic Intention Comparison
OA Developer's Diary-Part 4: Using OpenAmplify Via SOAP
OA Developer's Diary-Part 5: OpenAmplify's Influence on Non-Technical Decisions
Justin James has
more than 20 years experience in the IT Industry. He has worked in
many roles including his work as an application developer, network
engineer, and help desk guru. His current position is a mix of network
engineering, systems administration, and “utility programming,” but he
is recently been focusing on the development of his company’s primary
product. In his extra time Justin is a well known technology blogger
for CNET Networks TechRepublic Brand. If that was not enough he uses
his spare time writing code and trying new things. Over the next few
weeks Justin will write a developer’s diary about using OpenAmplify in
his document comparison project. Along the way he will discuss what
went well and what didn’t and include useful code samples for working
with OpenAmplify in C#.
Posted
3 Nov 2009 1:58 PM
by
AngelaLawson