Chapter 6. Understanding Text

The previous chapter covered the speech APIs. Throughout this chapter, we will look closer at more language APIs. We will learn how to use spellcheck features. We will then discover how to detect languages, key phrases, and sentiment in text. Finally, we will look at the translator text API to see how we can detect languages and translate text.

By the end of this chapter, we will have covered the following topics:

  • Checking spelling and recognizing slang and informal language, common names, homonyms, and brands
  • Detecting language, key phrases, and sentiment in text
  • Translating text on the fly

Setting up a common core

Before we get into the details, we want to set ourselves up for success. At the time of writing, none of the language APIs that we will be covering have NuGet client packages. As such, we will need to call directly to the REST endpoints. Because of this, we will do some work beforehand to make sure that we get away with writing less code.

New project

We will not be adding the APIs to our smart-house application. Using the following steps, create a new project using the MVVM template that we created in Chapter 1, Getting Started with Microsoft Cognitive Services:

  1. Go into the NuGet package manager and install Newtonsoft.Json. This will help us deserialize API responses and serialize request bodies.
  2. Right-click on References.
  3. In the Assemblies tab, select System.Web and System.Runtime.Serialization.
  4. Click OK.
  5. In the MainView.xaml file, add a TabControl element. All our additional views will be added as TabItems in the MainView.

Web requests

All the APIs follow the same pattern. They call on their respective endpoints using either POST or GET requests. Further on, they pass on parameters as query strings, and some as request bodies. Since they have these similarities, we can create one class that will handle all API requests.

In the Model folder, add a new class and call it WebRequest.

We also need a few private variables, as follows:

    private const string JsonContentTypeHeader = "application/json";

    private static readonly JsonSerializerSettings _settings = new JsonSerializerSettings
    {
        DateFormatHandling = DateFormatHandling.IsoDateFormat,
        NullValueHandling = NullValueHandling.Ignore,
        ContractResolver = new CamelCasePropertyNamesContractResolver()
    };

    private HttpClient _httpClient;
    private string _endpoint;

The constant, JsonContentTypeHeader, defines the content type that we want to use for all API calls. The _settings phrase is a JsonSerializerSettings object, which specifies how we want JSON data to be (de)serialized.

The _httpClient is the object that will be used to make our API requests. The last member, _endpoint, will hold the API endpoint.

As shown in the following code, our constructor will accept two parameters: one string for the URI, and one string for the API key:

    public WebRequest(string uri, string apiKey)
    {
        _endpoint = uri;
               
        _httpClient = new HttpClient();
        _httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
    }

We assign the uri to the corresponding member. Next, we create a new object of a HttpClient type and add one request header. This is the header that contains the given apiKey.

The class will contain one function, MakeRequest. This should have the return type of Task<TResponse>, meaning a type that we specify when calling the function. As you can see in the following code, it should accept three parameters: a HttpMethod, a query string, and a TRequest, (which is a request body that we specify in the call). The function should be asynchronous:

public async Task <TResponse> MakeRequest <TRequest, TResponse (HttpMethod method, string queryString, TRequest requestBody = default(TRequest))

The preceding lines show the complete function signature. Note how we do not need to specify a request body, as there are some cases where it may be empty. We will cover what TRequest and TResponse may be in a bit.

We enter a try clause, as shown in the following code:

    try {
        string url = $"{_endpoint}{queryString}";
        var request = new HttpRequestMessage(method, url);

        if (requestBody != null)
            request.Content = new StringContent (JsonConvert.SerializeObject(requestBody, _settings), Encoding.UTF8, JsonContentTypeHeader);

        HttpResponseMessage response = await _httpClient.SendAsync(request);

First, we create a url, consisting of our _endpoint and the queryString. Using this and the specified method, we create a HttpRequestMessage object.

If we have a requestBody, we add Content to the request object by serializing the requestBody.

With the request in order, we make an asynchronous call to SendAsync on the _httpClient object. This will call the API endpoint, returning a HttpResponseMessage containing the response.

If the response is successful, we want to get the Content as a string. This is done as follows:

  1. Make an asynchronous call to ReadAsStringAsync. This will return a string.
  2. Deserialize the string as a TResponse object.
  3. Return the deserialized object to the caller.

In the case that there is no data in responseContent, we return a default TResponse. This will contain default values for all properties, as shown in the following code:

    if (response.IsSuccessStatusCode)
    {
        string responseContent = null;
       
        if (response.Content != null)
            responseContent = await response.Content.ReadAsStringAsync();
        if (!string.IsNullOrWhiteSpace(responseContent))
            return JsonConvert.DeserializeObject<TResponse>(responseContent,_settings);

        return default(TResponse);
    }

If the API response contains any error code, then we try to get the error message as a string (errorObjectString). In a typical application, you would want to deserialize this and propagate it to the user. However, as this is a simple example application, we will choose to output it to the Debug console window, as shown in the following code:

    else
    {
        if (response.Content != null && response.Content.Headers.ContentType.MediaType.Contains (JsonContentTypeHeader))
        {
            var errorObjectString = await response.Content.ReadAsStringAsync();
            Debug.WriteLine(errorObjectString);
        }
    }

Make sure you add the corresponding catch clause and output any exceptions to the Debug console window. Also, make sure that you return a default TResponse if any exceptions occur.

Data contracts

As we need to (de)serialize JSON data as a part of the requests and responses to the APIs, we need to create data contracts. These will act as the TResponse and TRequest objects, used in the WebRequest class.

Add a new folder called Contracts to the project. A typical data contract may look like the following:

    [DataContract]
    public class TextErrors {
       [DataMember]
       public string id { get; set; }

       [DataMember]
       public string message { get; set; }
    }

This correlates to errors in the text analytics API. As you can see, it has two string properties for id and message. Both may appear in an API response.

When discussing each API, we will see all request and response parameters in either table form or JSON format. We will not look at how each of these translates into a data contract, but it will take a similar form to that previously shown. It is then up to you to create the contracts needed.

The most important thing to note is that the property names must be identical to the corresponding JSON property.

Make sure that the code compiles and that you can run the application before continuing.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset