Silverlight in the Mesh and the “Cloud” – Hosted Service and Blob Storage (Part 2)

January 15, 2009

Hello. As I promised here I’m starting to describe my experiences in creating Silverlight Mesh Enabled Web Application (MEWA or SMEWA) with Cloud Hosted Services and Cloud Storage.

Today I’ll talk about creating the storage and supported hosted services.

First of all I needed to be a part of Windows Azure CTP and have at least 1 Storage account (to have persistent and non-persistent storage in Windows Azure) and at least 1 Hosted Services account (environment that provides the hosting and management service for cloud based applications).

To get such account(s) one should apply for them via Microsoft Connect site.

After getting invitation to this program from Microsoft Connect you could go to Azure Services Developer Portal, claim received tokens, download and install Windows Azure SDK and Windows Azure Tools Visual Studio and start creating cloud based applications. One small note here – those tools doesn’t support Windows 7 Beta right now, so it will not work there.

Once all setup done, we could go to Azure Services Developer Portal and create a new project:

image

I created 1 for Storage

image

(Endpoints are gateways that I could use from anywhere when accessing my storage account, and pair of key access is to secure my connection.)

Another project was created for Hosted Services

You could have 2 projects simultaneously running at the cloud – one for testing/debugging online and one as a real production service. The URL for the service in Staging will change every time you will re-deploy the new version of the service, thus you have to reconfigure your applications which will work with those services externally.

 image

Now back to my “Cloud Store”. I decided to provide access to my cloud storage via Web Services and those web services will be in my Host Services Project.

After installing Windows Azure Tools for Visual Studio you will get new project templates:

image

For my purposes I’ve created Web Cloud Service. In my service I’ve added 2 new web services – one which will be used by Content Management UI SMEWA, and one by Content Consumer UI SMEWA. I wish I had more Hosted Services projects allocated to use different projects for each application, but I haven’t. Also, I could use the same service for both applications but I wanted the whole thing to me close to the real world architecture.

When you creating such a project Visual Studio will create 2 projects in the solution – ASP.NET Web Application and the Web Cloud Service Project:

image

In my case I’ve also added 2 exiting projects from Windows Azure SDK Samples (Common and Storage Client) which will handle for me all communications with the blob.

Now to the interesting part. Lets see how to work with the blob storage. Most of the “real mesh code” was taken from PCD demos and samples from Windows Azure SDK so if you need more info you know where to find it.

Let’s see  the FileUpload WebMethod as an example:

[WebMethod]
public bool UploadFile(string fileName, string contentType ,byte[] f)
{
  //Assume success - its good to be optmistic 🙂
  bool bRes = true;
  try
  {
    // Get the configuration from the cscfg(cloud service configuration) file
    StorageAccountInfo accountInfo = StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration();
 
    // Container names have the same restrictions as DNS names
    BlobStorage blobStorage = BlobStorage.Create(accountInfo);
    _Container = blobStorage.GetBlobContainer(RoleManager.GetConfigurationSetting("ContainerName"));
 
    // returns false if the container already exists, ignore for now
    // Make the container public so that we can hit the URLs from the web
    _Container.CreateContainer(new NameValueCollection(), ContainerAccessControl.Public);
 
    BlobProperties properties = new BlobProperties(Guid.NewGuid().ToString());
 
    // Create metadata to be associated with the blob
    NameValueCollection metadata = new NameValueCollection();
    metadata["FileName"] = fileName;
 
    properties.Metadata = metadata;
    properties.ContentType = contentType;
 
    // Create the blob
    BlobContents fileBlob = new BlobContents(f);
    _Container.CreateBlob(properties, fileBlob, true);
  }
  catch (WebException webExcept)
  {
    bRes = false;
    if (webExcept.Status == WebExceptionStatus.ConnectFailure)
      System.Diagnostics.Debug.WriteLine("Failed to connect to the Blob Storage Service, make sure it is running: " + webExcept.Message);
    else
      System.Diagnostics.Debug.WriteLine("Error creating container: " + webExcept.Message);
  }
  catch (Exception ex)
  {
    bRes = false;
    System.Diagnostics.Debug.WriteLine(ex.Message);
  }
 
  return bRes;
}

The code itself is pretty easy – create or get blob container, fill new blob properties and metadata and the create new blob to the container.

Same goes for DeleteFile WebMethod

[WebMethod]
public bool DeleteFile(string fileName)
{
  bool bRes = true;
 
  // Get the configuration from the cscfg file
  StorageAccountInfo accountInfo = StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration();
 
  // Container names have the same restrictions as DNS names
  BlobStorage blobStorage = BlobStorage.Create(accountInfo);
  _Container = blobStorage.GetBlobContainer(RoleManager.GetConfigurationSetting("ContainerName"));
 
  //Check if desired blob exists, and if it does - delete it
  if (_Container.DoesBlobExist(fileName))
    bRes = _Container.DeleteBlob(fileName);
 
  return bRes;
}

Last, but not least is I want to able to show blob contents in my management SMEWA, so I created GetFiles WebMethod

[WebMethod]
public List<ContentEntry> GetFiles()
{
  // Get the configuration from the cscfg file
  StorageAccountInfo accountInfo = StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration();
 
  // Container names have the same restrictions as DNS names
  BlobStorage blobStorage = BlobStorage.Create(accountInfo);
  _Container = blobStorage.GetBlobContainer(RoleManager.GetConfigurationSetting("ContainerName"));
 
  //Get blobs in my account
  IEnumerable<object> blobs = _Container.ListBlobs(string.Empty, false);
  List<ContentEntry> filesList = new List<ContentEntry>();
 
  foreach (object o in blobs)
  {
    BlobProperties bp = o as BlobProperties;
    if (bp != null)
    {
      //Get current blob properties
      BlobProperties p = _Container.GetBlobProperties(bp.Name);
      NameValueCollection fileEntryProperties = p.Metadata;
      //Create data container which will return relevan information to the client
      filesList.Add(new ContentEntry() { BlobName = p.Name, FileUri = bp.Uri.ToString(), FileName = fileEntryProperties["FileName"], Submitter = "ALEX" });
    }
  }
 
  return filesList;
}

The ContentEntry class itself is pretty simple also:

 

public class ContentEntry
{
  public ContentEntry()
  {
  }
 
  public ContentEntry(string blobName, string fileAddress, string name, string user)
  {
      BlobName = blobName;
      FileUri = fileAddress;
      FileName = name;
      Submitter = user;
  }
 
  public string FileUri { get; set; }
 
  public string BlobName { get; set; }
 
  public string FileName { get; set; }
 
  public string Submitter { get; set; }
}

After doing all that, I had to configure my service to work with local development storage. Configuration settings for cloud services defined in file named “ServiceDefinition.csdef”. In my case it is like follows:

<ServiceDefinition name="StoreBusinessTier" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <InputEndpoints>
      <!-- Must use port 80 for http and port 443 for https when running in the cloud -->
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
    <ConfigurationSettings>
      <Setting name="AccountName"/>
      <Setting name="AccountSharedKey"/>
      <Setting name="BlobStorageEndpoint"/>
      <Setting name="ContainerName"/>
    </ConfigurationSettings>
  </WebRole>
</ServiceDefinition>

And the actual values for those configuration settings are in “ServiceConfiguration.cscfg” file:

<ServiceConfiguration serviceName="StoreBusinessTier" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="WebRole">
    <Instances count="1"/>
    <ConfigurationSettings>
      <!--Local Develoment Storage Account Settings-->
      <Setting name="AccountName" value="devstoreaccount1"/>
      <Setting name="AccountSharedKey" value="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="/>
      <Setting name="BlobStorageEndpoint" value="http://127.0.0.1:10000/"/>
      
      <!--Real Cloud Storage Settings-->
      <!--<Setting name="AccountName" value="STORAGE_PROJECT_NAME"/>
      <Setting name="AccountSharedKey" value="PRIMARY_ACCESS_KEY"/>
      <Setting name="BlobStorageEndpoint" value="https://blob.core.windows.net"/>-->
 
      <Setting name="ContainerName" value="files"/>
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

Compiling an executing the application will bring Developer Storage

image 

and the Development Fabric

 image

and finally IE with standard ASP.NET Web Application debugging experience. In my case the WebService was a start-up file, so I’ve got this:

image

My second web service has pretty simple functionality – Listing the exiting files and getting the specific file content:

image

GetFile WebMethod should return me the list of files (like FileHandler web service) – I thought I could even use the one from FileHandler… I thought so, but it will not work – will see why in last part.

GetFile WebMethod should return me the contents of the selected file (byes[] or Stream or something) – pretty easy task… Hm… This one was actually not trivial as it turns out – will see why also in last part.

 

Last thing I did after checking this service locally with some tester application I’ve deployed this service to the cloud and started to work on my SMEWA:

image

 

Stay tuned for the next part.

This part will connect the two worlds which are very close, but somehow not connected until now -  I will show how to create management SMEWA and use Azure Storage (blob) and Azure Hosted Services (I just created here) to save the data from Live Mesh Application to the Windows Azure Storage.

 

 

Enjoy,

Alex

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

5 comments

  1. RobJanuary 15, 2009 ב 19:51

    So, is there no way to run a WCF service in the cloud?

    Reply
  2. Alex GoleshJanuary 15, 2009 ב 20:06

    Never tried, but think it is possible. Will check it and try to provide something in next parts.

    Regards,
    Alex

    Reply
  3. KhuramMarch 3, 2009 ב 7:45

    Hi,

    If possible can you arrange code for above demo?

    Thanks,

    Reply
  4. Alex GoleshMarch 5, 2009 ב 5:07

    Khuram:
    You need to be a part of Windows Asure CTP. If you are not it will not help.
    Anyway, the source for this demo has too many references with my IDs/Keys for Azure CTP, that I will not be able to clean them up without break something in the demo.

    Sorry,
    Alex

    Reply
  5. ChadwickJanuary 30, 2013 ב 20:43

    I could not refrain from commenting. Well written!

    Reply