MVC ASP.NET and Microsoft Translator

Introduction

The Internet is moving towards restful services, where we use the HTTP protocol to get information from services. If we just need to send some values into the service and get a return back, then we can use a GET HTTP request. A good example of this is with Microsoft Translator, where we can call up the Translator API with a text value, and with the arguments of the input and the output languages (such as en for English and fr for French). In this tutorial I will illustrate how we can integrate Microsoft Translator into an ASP.NET MVC site. If you want to view the result it is here, which uses both a text translator, and a speech convertor.

Getting the Authentication Token

In order to access the service, we must first create an authentication token, which, once granted, is added to the HTTP Web request. The standard code to use is:

[DataContract]
        public class AdmAccessToken
        {
            [DataMember]
            public string access_token { get; set; }
            [DataMember]
            public string token_type { get; set; }
            [DataMember]
            public string expires_in { get; set; }
            [DataMember]
            public string scope { get; set; }
        }
        public class AdmAuthentication
        {
            public static readonly string DatamarketAccessUri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
            private string clientId;
            private string cientSecret;
            private string request;

            public AdmAuthentication(string clientId, string clientSecret)
            {
                this.clientId = clientId;
                this.cientSecret = clientSecret;
                //If clientid or client secret has special characters, encode before sending request
                this.request = string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=http://api.microsofttranslator.com", HttpUtility.UrlEncode(clientId), HttpUtility.UrlEncode(clientSecret));
            }

            public AdmAccessToken GetAccessToken()
            {
                return HttpPost(DatamarketAccessUri, this.request);
            }

            private AdmAccessToken HttpPost(string DatamarketAccessUri, string requestDetails)
            {
                //Prepare OAuth request 
                WebRequest webRequest = WebRequest.Create(DatamarketAccessUri);
                webRequest.ContentType = "application/x-www-form-urlencoded";
                webRequest.Method = "POST";
                byte[] bytes = Encoding.ASCII.GetBytes(requestDetails);
                webRequest.ContentLength = bytes.Length;
                using (Stream outputStream = webRequest.GetRequestStream())
                {
                    outputStream.Write(bytes, 0, bytes.Length);
                }
                using (WebResponse webResponse = webRequest.GetResponse())
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AdmAccessToken));
                    //Get deserialized object from JSON stream
                    AdmAccessToken token = (AdmAccessToken)serializer.ReadObject(webResponse.GetResponseStream());
                    return token;
                }
            }

This is then called by:

       AdmAuthentication admAuth = new AdmAuthentication("CLIENT ID", "CLIENT SECRET");
       admToken = admAuth.GetAccessToken();
       Session["admToken"] = admToken;

where we keep the token as a session key, which is used for other accesses. To create the CLIENT ID and CLIENT SECRET we go to.

http://datamarket.azure.com/

and then click on Register Your Application (which is near the bottom of the page).  In the example below the CLIENT ID is french and the CLIENT SECRET is /fspbEcYHaX/TOm1TlDJAoeK6oMe7q0k9wDhTvl1gic=:

azCreating the controller

The controller has a GET and a POST, where the GET is called when the page is first accessed, and the POST results from the user clicking on the Translate button. With the code the getTranslation() method will return a translation of text, from English (“en”) to French (“fr”) and the getTranslationSp() method will return a wav file link for the translation.

 [HttpPost]
        public ActionResult french(FormCollection Form)
        {
            string text = Form["english"];
            AdmAccessToken admToken  = (AdmAccessToken)Session["admToken"];
            ViewData["english"] = text;
            string rtn = getTranslation(admToken,text, "en", "fr");
            ViewData["french"] = rtn;
            rtn = getTranslationSp(admToken,rtn, "fr");
            ViewData["audio"] = rtn;
            return PartialView("french_partial");
        }

        [HttpGet]
        public ActionResult french(string text)
        {
            string rtn = "";
            AdmAccessToken admToken;
            AdmAuthentication admAuth = new AdmAuthentication("CLIENT ID", "CLIENT SECRET");
            admToken = admAuth.GetAccessToken();
            Session["admToken"] = admToken;
            if (text != null)
            {
                rtn = getTranslation(admToken,text, "en", "fr");
                ViewData["french"] = rtn;
                rtn = getTranslationSp(admToken, rtn, "fr");
                ViewData["audio"] = rtn;
                ViewData["english"] = text;
            }
            return View();
        }

the methods for the translation can then be added:

 public string getTranslation(AdmAccessToken admToken, string text, string from, string to)
        {
            try
            {
                string uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + System.Web.HttpUtility.UrlEncode(text) + "&from=" + from + "&to=" + to;
                string authToken = "Bearer" + " " + admToken.access_token;

                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
                httpWebRequest.Headers.Add("Authorization", authToken);

                WebResponse response = httpWebRequest.GetResponse();
                using (Stream stream = response.GetResponseStream())
                {
                    System.Runtime.Serialization.DataContractSerializer dcs = new System.Runtime.Serialization.DataContractSerializer(Type.GetType("System.String"));
                    string translation = (string)dcs.ReadObject(stream);
                    return (translation);
                }
            }
            catch (Exception ex)
            {
                return ("Not Known (" + ex.Message + ")");
            }
            return ("");
        }
        public string getTranslationSp(AdmAccessToken admToken, string text, string from)
        {
            try
            {
                string uri = "http://api.microsofttranslator.com/v2/Http.svc/Speak?text="+text+"&language="+from+"&format=" + HttpUtility.UrlEncode("audio/wav") + "&options=MaxQuality";
                string authToken = "Bearer" + " " + admToken.access_token;
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
                request.Headers.Add("Authorization", authToken);

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                // Get the stream associated with the response.
                Stream receiveStream = response.GetResponseStream();
                byte[] buffer = new byte[32768];
               string fname = "cc/"+System.Guid.NewGuid().ToString()+".wav";
               using (FileStream fileStream = System.IO.File.Create(Server.MapPath("~/") + fname))
                {
                    while (true)
                    {
                        int read = receiveStream.Read(buffer, 0, buffer.Length);
                        if (read <= 0)
                            break;
                        fileStream.Write(buffer, 0, read);
                    }
                }
                ViewData["file"] = "/" + fname;
            }
            catch (Exception ex)
            {
                return ("Audio error: (" + ex.Message + ")");
            }
            string filename = "/" + fname;
            return (filename);
        }

Creating the view

Now we need to create the view using Ajax with (french.cshtml):

@{
    ViewBag.Title = "French Translation";
}

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<!-- ~/Scripts/jquery.validate.unobtrusive.js -->

 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

        <script>
            function DHTMLSound(surl) {
  document.getElementById("dummyspan").innerHTML=
    "";
}
        </script>

    <table width="100%" border="1" cellpadding="0" cellspacing="0">

      <tr><td valign="top" colspan="2"><div> <h1>English to French</h1></div>
<div> &nbsp;</div>
           <div>
<p><a href="javascript:history.go(-1)">Back</a> Press the button for the translation:</p>

           @using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "french_partial", HttpMethod = "POST", InsertionMode = InsertionMode.Replace }))
            {           

                      <div id="french_partial">
 @Html.Partial("french_partial")
</div>             }     
               </div>
</td></tr>
    </table>

and a partial view of (french_partial.cshtml):

<table width="100%" border="0">
  <tr>   
    <td width="50%" valign="top" bgcolor="#F8F8FF">
        <h2>Parameters</h2>
        <div>
       <div>Enter English phrase:</div><div> @Html.TextArea("english", null, new { style = "width:400px" })
        <input type="submit" id="buttoncheckanswer" value="Translate" name="button1" /> </div>   
 </div>
</td>
    <td width="50%" valign="top"><h2>Translation</h2>
<p>Translation is: @ViewData["french"]</p> 
<form><input type="button" value="Play Translation" onClick="DHTMLSound('@ViewData["file"]')">
</form>
        <span id=dummyspan></span>
    </td>
  </tr>
</table>

Notice that ViewData[“file”] is used to point to the WAV file that has been created on the system, and that ViewData[“french”] is the translated text. So, try it here (just click on the graphic to try):

az2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s