AZURE, Silververlight, WCF

Upload Image from Silverlight to Azure BLOB using WCF

Working with Azure Blob is very common task you must be doing. Sometime you may come with requirement to upload an image from Silverlight client to Azure BLOB. In this post I am trying to help you in achieving this.

In this post I will show you below three stuffs.

  1. Uploading Image to Azure BOLB
  2. Abstracting BLOB upload code in WCF service
  3. Using WCF Service in Silverlight client to upload the image.

Expected Output

image

Flow of application

Step 1: On click event of Button File Dialog will open

Step 2: User will select Image and on selection Image will get uploaded in Azure Blob.

Step 3: On successful uploading URI of image will be returned from the service. Source property of Image control would be set to the returned URL.

Creating Service

Service Contract will have an function expose as operation contract as below,


[ServiceContract]
public interface IBLOBImageUpload

{

[OperationContract]
string UploadImage(byte[] Image);

}

Service is implemented as below,

  • We are creating a new GUID to set as file name of the image
  • Converting input byte array to stream
  • Calling a function to upload stream to blob
  • And returning URL of uploaded image

public string  UploadImage(byte[] Image)
{
string rowKeynFileName = Guid.NewGuid().ToString();
System.IO.Stream stream = new System.IO.MemoryStream(Image);
string imageUri= UploadImageinBlob(stream, rowKeynFileName );
return imageUri;

}

Function to upload Image in BLOB is as below

  • It is taking stream as input to upload
  • It is taking filename to be given to upload image
  •  DataConnectionString is connection string to Azure storage.
  •  urlContainer is name of the public container
  • Creating blob name by appending .jpg extension
  • Returning URL of uploaded image.


public string UploadImageinBlob(Stream Streams,string FileName)
{
CloudStorageAccount account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"));
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("urContainer");
string uniqueBlobName = string.Format("{0}.jpg", FileName);
CloudBlob blob = container.GetBlobReference(uniqueBlobName);
blob.Properties.ContentType = "image\\jpeg";
Streams.Seek(0, SeekOrigin.Begin);
blob.UploadFromStream(Streams);
string url = blob.Uri.OriginalString;
Streams.Close();
return url;

}

Configuring Service EndPoint

There are many points you need to put in mind while configuring the service end point.

  • Change maxReceivedMessageSize to 2147483647
  • Change maxBufferSize to 2147483647
  • Change maxArrayLength to 2147483647
  • Change maxBytePerRead to 2147483647
  • Change maxDepth to 2147483647
  • Change maxTableCharCount to 2147483647
  • Change maxStringContentLength to 2147483647
  • In Service behavior change data contract serliazer max object graph value to 2147483647


<system.serviceModel>

<bindings>

<basicHttpBinding>

<binding name="ServicesBinding"

maxReceivedMessageSize="2147483647"

maxBufferSize="2147483647">

<readerQuotas

maxArrayLength="2147483647"

maxBytesPerRead="2147483647"

maxDepth="2147483647"

maxNameTableCharCount="2147483647"

maxStringContentLength="2147483647" />

</binding>

</basicHttpBinding>

</bindings>

<services>
<service name="Service.BLOBImageUpload" behaviorConfiguration="ServiceData.Service1Behavior">

<endpoint address="" binding="basicHttpBinding" contract=" Service.IBLOBImageUpload " bindingConfiguration ="ServicesBinding" />

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

</service>

</services>

<behaviors>

<serviceBehaviors>

<behavior name ="ServiceData.Service1Behavior">

<serviceMetadata httpGetEnabled="true"/>

<serviceDebug includeExceptionDetailInFaults="false"/>

<dataContractSerializer maxItemsInObjectGraph ="2147483647"/>

</behavior>

</serviceBehaviors>

</behaviors>

<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

</system.serviceModel>

&nbsp;

Now your service is written. You can choose service to host anywhere you want.

Creating UI

I have kept UI as sweet and simple as possible. There is just a button and image control. On click of button FileDialogBOX will open and user can select an image to upload. After successful uploading, URL of uploaded image in Azure blob will be returned and that will be set as source of Image control


<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>

<RowDefinition Height="100" />
<RowDefinition Height="*" />

</Grid.RowDefinitions>

<Button x:Name="btn" Height="100" Width="100" Click="btn_Click" Content="Upload Image" />
<Image Grid.Row="1" x:Name="img" Height="auto" Width="auto" />
</Grid>

&nbsp;

Calling Service

You need to make a normal service call

  • On click event of the button opening the file dialog
  • Converting stream to byte array
  • Passing byte array as input to the function.
  • GetImageSource function is converting given string URL as image source to be set as source of image control


public partial class MainPage : UserControl
{

public OpenFileDialog fileDialog = null;
public MainPage()
{
InitializeComponent();
}

private void btn_Click(object sender, RoutedEventArgs e)
{
Stream strm;
byte[] buffer = null; ;
fileDialog = new OpenFileDialog();
fileDialog.Multiselect = false;
fileDialog.Filter = "All Files|*.*";
bool? retval = fileDialog.ShowDialog();
if (retval != null && retval == true)
{
strm = fileDialog.File.OpenRead();
buffer = new byte[strm.Length];
strm.Read(buffer, 0, (int)strm.Length);
}

BLOBImageUploadClient proxy = new BLOBImageUploadClient ();

proxy.UploadImageAsync(buffer);
proxy.UploadImageAsync += new EventHandler<UploadImageCompletedEventArgs>(proxy_UploadImageCompleted);
}

void proxy_UploadImageCompleted (object sender, UploadImageCompletedEventArgs e)
{

img.Source = GetImageSource(e.Result.ToString());
}

private ImageSource GetImageSource(string fileName)
{
return new BitmapImage(new Uri(fileName, UriKind.Absolute));
}

}
}

&nbsp;

This is what all you need to do as far as coding is concern. Yes you may need to put clientacccesspolicy.xml at the root location of server where you are hosting WCF service to avoid cross domain problem.

I hope this post was useful. Thanks for reading Smile

If you find my blogs useful you may like to,

Follow me on twitter http://twitter.com/debug_mode

Like Facebook page of this blog http://www.facebook.com/DebugMode.Net

If you want to see post on a particular topic please do write on FB page or tweet me about that, I would love to help you.

About Dhananjay Kumar

Dhananjay Kumar is Developer, Blogger , Speaker, Learner , Mindcracker & Microsoft MVP.

Discussion

12 Responses to “Upload Image from Silverlight to Azure BLOB using WCF”

  1. Hi,

    Where can I download the source code for this?

    Thanks

    Fernan

    Posted by Fernan | October 22, 2011, 2:12 pm
  2. Hi Andy ,

    If you provide me more input that where exactly code is not working then I would be in better position to help you. However I have posted this code after many rounds of testing. Waiting for your response

    Posted by Dhananjay Kumar | October 24, 2011, 6:26 pm
  3. Thanks Andy. Anyway, the link you provide is kinda hard to understand for a newbie like me. I like this one but I cannot make it run in Visual Studio. CAn anyone help me understand this line below?

    public string UploadImage(byte[] Image)
    {
    string rowKeynFileName = Guid.NewGuid().ToString();
    System.IO.Stream stream = new System.IO.MemoryStream(obj.Image);
    string imageUri= UploadImageinBlob(stream, obj.RecordId);
    return imageUri;

    }

    Where or how can I get the obj.Image? and obj.RecordID?

    regards,

    Fernan

    Posted by Fernan | October 24, 2011, 7:40 pm
  4. Oh My bad ;

    public string UploadImage(byte[] Image)
    {
    string rowKeynFileName = Guid.NewGuid().ToString();
    System.IO.Stream stream = new System.IO.MemoryStream(Image);
    string imageUri= UploadImageinBlob(stream, rowKeynFileName );
    return imageUri;

    }

    I have modifed the code .. it should work now .. Thanks

    Posted by Dhananjay Kumar | October 25, 2011, 7:24 am
  5. Thanks Dhananjay

    I got it working. One question, why is it when I upload an image, the filename changes to something else on my blob storage.

    Sorry, I am a newbie on using Silverlight to Azure Blob. But I can follow your codes here. It helps a lot.

    Regards,

    Fernan

    Posted by Fernan | October 25, 2011, 2:34 pm
  6. Hi ,

    Instead of rowKeynFileName pass your original file name . Thanks

    Posted by Dhananjay Kumar | October 25, 2011, 5:15 pm
  7. Thanks Dhananjay.

    But I think this is what I need because it avoid to have duplicate filenames. Another question as I observe in the connection string:

    CloudStorageAccount account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(“DataConnectionString”));

    returns an error saying “External component has thrown an exception.”

    But if I use this one it works(I got this on another forum);

    CloudStorageAccount account = CloudStorageAccount.Parse(“BlobEndpoint=http://mystorage.blob.core.windows.net;AccountName=mystoragename;AccountKey=5Un0WU6Flo43yHVM8lgZpi7QLLwdXpZnACQTlw4U3PFUilqV4NT1penwG/Cw252KRNZkv42HdZAAHUGcZkKnlQ==”);

    Below is my ServiceConfiguration;

    Please advise.

    - Fernan

    Posted by Fernan | October 26, 2011, 8:24 am
  8. Thanks Dhananjay.

    But I think this is what I need because it avoid to have duplicate filenames. Another question as I observe in the connection string:

    CloudStorageAccount account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(“DataConnectionString”));

    returns an error saying “External component has thrown an exception.”

    But if I use this one it works(I got this on another forum);

    CloudStorageAccount account = CloudStorageAccount.Parse(“BlobEndpoint=http://mystorage.blob.core.windows.net;AccountName=mystoragename;AccountKey=5Un0WU6Flo43yHVM8lgZpi7QLLwdXpZnACQTlw4U3PFUilqV4NT1penwG/Cw252KRNZkv42HdZAAHUGcZkKnlQ==”);

    Below is my ServiceConfiguration;

    Please advise.

    - Fernan

    Posted by Fernan | October 26, 2011, 8:28 am
  9. Hi Dhananjay,

    can you clarify this “one you may need to put clientacccesspolicy.xml at the root location of server ”

    I want to upload my project to Azure Cloud.

    Please advise.

    Regards,

    Fernan

    Posted by Fernan | October 27, 2011, 9:16 am
  10. HI ,

    Very First you should not disclose your connection string publicly like this in comment . You can do like

    string DataConnectionString = “(“BlobEndpoint=http://mystorage.blob.core.windows.net;AccountName=mystoragename;AccountKey=5Un0WU6Flo43yHVM8lgZpi7QLLwdXpZnACQTlw4U3PFUilqV4NT1penwG/Cw252KRNZkv42HdZAAHUGcZkKnlQ==”” ;

    and then use

    CloudStorageAccount account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(“DataConnectionString”));

    Just to avoid disclosing my Connection string , I used data coneection string and you need to replace the string with your original string.

    Second part about cross domain file. Right click on WCF Service Role , add exisiting item and then choose CrossDomain File . That is what all you need to do to place cross domain in root.

    I hope this helps

    Posted by Dhananjay Kumar | October 27, 2011, 9:52 am

Trackbacks/Pingbacks

  1. Pingback: Monthly Report September 2011: Total Posts 28 « debug mode…… - October 1, 2011

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 )

Connecting to %s

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 1,380 other followers

Tweets

Categories

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my current or previous employer's view in anyway. © Copyright 2012