Tuesday, November 23, 2010

Moscow, MS Platforma 2011

I just returned from MS Platforma Conference in Moscow.

It is the biggest IT event in Russia - to popularize Microsoft Software, solutions, and talk about what's new among Russian and a few former "CCCP" IT specialists.

This time it coincided with Microsoft Lync launch - I am also a developer for Lync at Microsoft Zurich Development Center. I participated in two cojoint talks about Lync: gave a demo on Lync Architecture session and talked about dial-in conferencing in another session.

The conference was greatly organized and was an excellent experience.
Hope to be invited to go there next year as well:)

Here are some pics from the sessions:





There is a good blog by Sergey Trofimov, who participated in this event about this conference.

Monday, November 8, 2010

Uploading Files to Google App Engine

In previous post we talked about sending emails with attachments from the Google App Engine.
But how do we get files from a client to the cloud?

Here is a sample code in C#:

public static string UploadFilesToRemoteUrl(string url, string[] files, NameValueCollection nvc, string cookie)
{
    string boundary = "----------------------------" +
    DateTime.Now.Ticks.ToString("x");

    HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
    httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
    httpWebRequest.Method = "POST";
    httpWebRequest.KeepAlive = true;
    httpWebRequest.Headers["Cookie"] = cookie;
    httpWebRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;

    Stream memStream = new MemoryStream();

    byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

    string formdataTemplate = "\r\n--" + boundary +
        "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

    foreach (string key in nvc.Keys)
    {
        string formitem = string.Format(formdataTemplate, key, nvc[key]);
        byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
        memStream.Write(formitembytes, 0, formitembytes.Length);
    }

    memStream.Write(boundarybytes, 0, boundarybytes.Length);
    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\";filename=\"{1}\"\r\n\r\n";

    for (int i = 0; i < files.Length; i++)
    {
        string header = string.Format(headerTemplate, "file" + i, files[i]);
        byte[] headerbytes = Encoding.UTF8.GetBytes(header);

        memStream.Write(headerbytes, 0, headerbytes.Length);

        FileStream fileStream = new FileStream(files[i],
            FileMode.Open, FileAccess.Read);
        byte[] buffer = new byte[1024];

        int bytesRead = 0;

        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
        {
            memStream.Write(buffer, 0, bytesRead);

        }
        memStream.Write(boundarybytes, 0, boundarybytes.Length);
        fileStream.Close();
    }

    httpWebRequest.ContentLength = memStream.Length;

    Stream requestStream = httpWebRequest.GetRequestStream();

    memStream.Position = 0;
    byte[] tempBuffer = new byte[memStream.Length];
    memStream.Read(tempBuffer, 0, tempBuffer.Length);
    memStream.Close();
    requestStream.Write(tempBuffer, 0, tempBuffer.Length);
    requestStream.Close();

    WebResponse webResponse = httpWebRequest.GetResponse();

    Stream stream = webResponse.GetResponseStream();
    StreamReader reader = new StreamReader(stream);

    string responseFromServer = reader.ReadToEnd();

    webResponse.Close();
    reader.Close();
    stream.Close();
    httpWebRequest = null;
    webResponse = null;

    return responseFromServer;
}

The method above has a cookie as a parameter. Here is an excellent site by Dale Lane where you can see how to access authenticated Google App Engine service from a C# client.

Sunday, November 7, 2010

How to Send Email with Attachments Using Google App Engine

The cool thing about Google App Engine is that you can send e-mails from there for free (well, up to 2000 per day). You can even send attachments with it!

How do you do that? Here is a code snippet. Note that two cases are dealt here, one when there are attachments (so a multi part message is created) and the simplest case where there no attachments:


private static String SendEmail(String user, String to,
    String cc, String subject, String body, String filename,
    String mimeType, byte[] rawData)
{
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);

    MimeMessage message = new MimeMessage(session);

    try {
        message.setFrom(new InternetAddress(user));
        message.addRecipient(Message.RecipientType.TO,
                             new InternetAddress(to));
        if (cc != null && !cc.trim().isEmpty()) {
              message.addRecipient(Message.RecipientType.CC,
                             new InternetAddress(cc));                    
        }
        message.setSubject(subject, "UTF-8");

        if (rawData != null && filename != null &&
           !filename.isEmpty()) {
             if (mimeType == null || mimeType.isEmpty()) {
                 mimeType = GetMimeType(filename);
             }

             Multipart mp = new MimeMultipart();
             MimeBodyPart htmlPart = new MimeBodyPart();

             htmlPart.setContent(body, "text/html");
             mp.addBodyPart(htmlPart);
             ByteArrayDataSource dataSource = new
                 ByteArrayDataSource(rawData, mimeType);
     
             MimeBodyPart attachment = new MimeBodyPart();
             attachment.setFileName(filename);
             attachment.setDataHandler(
                 new DataHandler(dataSource));                                  
             mp.addBodyPart(attachment);

             message.setContent(mp);
         }
         else {
             message.setText(body, "UTF-8");
         }

         Transport.send(message);
     } catch (Exception e) {
          return "Error: " + e.getMessage();
     } 
     return "ok";
}

Wednesday, November 3, 2010

How to write a client to access Google App Engine with GWT

This tip is needed when you create a new Google App Engine project using Eclipse and choose the default settings, in particular when you leave Google Web Toolkit box checked (no trick needed if you uncheck it). If you always uncheck Google Web Toolkit you won't need this. You may still find useful the below example on how to access Google App Engine from a C# client.

The problem is that the framework will create for you all the skeletons for accessing the App Engine from the browser. But what if in addition you want to access the App Engine from a custom made client?

Passing regular parameters will not help - they won't be parsed correctly by the Google App Engine framework.
You need a custom parameter passed, that looks like this:

"5|0|6|http://1.latest.myapp.appspot.com/myapp/|SOMEGUID|myapp.clientGreetingService|greetServer|java.lang.String/2004016611|ThisIsAParameterValue|1|2|3|4|1|5|6|";


Here is the client in C# accessing Google App Engine (created from Eclipse with Web Toolkit option): 

WebRequest request = WebRequest.Create(   "http://1.latest.myapp.appspot.com/appname/greet");
request.Credentials = CredentialCache.DefaultCredentials;
request.Method = "POST";
request.ContentType = "text/x-gwt-rpc; charset=utf-8";

string content = "5|0|6|http://1.latest.myapp.appspot.com/myapp/|AF76B9CA2759BDA4DBA207D5542054B2|myapp.clientGreetingService|greetServer|java.lang.String/2004016611|ThisIsAParameterValue|1|2|3|4|1|5|6|";

byte[] contentBytes = System.Text.UTF8Encoding.UTF8.GetBytes(content);
request.ContentLength = contentBytes.Length;
using (Stream stream = request.GetRequestStream())
{
    stream.Write(contentBytes, 0, contentBytes.Length);
}

WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
Console.WriteLine(responseFromServer);

reader.Close();
response.Close(); 

In a nutshell, what is important is to provide the servlet name (greet server as in the example above) and then parameter types and values. Other values are not important, the Google App Engine parser just needs the number and placement of pipes.