Blog

All Blog Posts

Storing Files in SQL Server using WCF RIA Services and Silverlight – Wrap up

I recently completed a three part series which described how you can create a Silverlight LOB application that stores and displays documents using FILESTREAM Storage in SQL Server 2008. Here are the articles for your reference.
  1. Configuring FILESTREAM in your database and WCF RIA Services setup.
  2. Uploading and Saving files to the database from a Silverlight LOB application.
  3. Viewing files stored in the FILESTREAM from a Silverlight LOB application
I received a few requests to share source code so I decided to pull together a solution which contains the code from the three articles listed above. As a bonus I am including another tip—how to display the image within your Silverlight application.

Displaying a saved image in your Silverlight application

Here are the steps involved to get our image to display in our application.
  1. Add an Image control to your XAML.
  2. Add a SelectionChanged event handler to our Grid
  3. Add a method in our ViewModel to retrieve the File object based on a provided DocumentId.
  4. Add code in our View to render the File object as an image in our Image control.
1. Our XAML:
<Image x:Name="imgViewer" Width="100" Height="100" />

2. Add a SelectionChanged event handler on our gridview control.  First the XAML:
SelectionChanged="rgvDocuments_SelectionChanged"
How the handler in code:
private void rgvDocuments_SelectionChanged(object sender, SelectionChangeEventArgs e)
{
    if (rgvDocuments.SelectedItem != null)
    {
        imgViewer.Source = null;
        AccountDocument accountDocument = (AccountDocument) rgvDocuments.SelectedItem;
        ViewModel.GetDocumentFile(accountDocument.DocumentID);
    }
}

3. Our ViewModel changes to retrieve the File object.
Remember, when we bound the grid we bound to the AccountDocuments EntitySet, which included the Document object, but not the File object. We did this for performance reasons. We only retrieve the File when we need it, one File record at a time.
public event EventHandler DocumentLoaded;
private int _documentId = 0;
public Document SelectedDocument { get; set; }

public void GetDocumentFile(int documentId)
{
    _documentId = documentId;
    var batch = new DomainContextLoadBatch(DocumentLoadComplete);
    batch.Add(Context.Load(Context.GetDocumentWithFileByIdQuery(documentId)));
}

private void DocumentLoadComplete(DomainContextLoadBatch batch)
{
    try
    {
        if (batch.FailedOperationCount > 0)
        {
            //foreach (var op in batch.FailedOperations)
            //    HelperFunctions.ProcessException(new Exception(op.Error.Message, op.Error.InnerException), "ProspectDetailsViewModel.cs");
            DataLoadError(this, null);
        }
        else
        {
            //Got the data - notify the view
            SelectedDocument = Context.Documents.Where(f => f.DocumentID == _documentId).FirstOrDefault();
            DocumentLoaded(this, null);
        }
    }
    catch (Exception ex)
    {
        throw;
    }
}

4. Add code in our view to fill our Image object from the returned File object.
This code example assumes we wired up the DocumentLoaded event handler when the view was initialized.
        void ViewModel_DocumentLoaded(object sender, EventArgs e)
        {
            try
            {
                if (ViewModel.SelectedDocument != null)
                {
                    byte[] imageBytes = ViewModel.SelectedDocument.File.DocumentFile;
                    var bitmapImage = new BitmapImage();
                    var stream = new MemoryStream(imageBytes);
                    bitmapImage.SetSource(stream);
                    imgViewer.Source = bitmapImage;
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

Notice that we simply take our byte array from our File object and use it to create a BitmapImage. This can then be assigned as the Source of the Image. Cool stuff!

Here is the complete solution for you to download. It comes as-is and with no warranties, but I hope it is useful.

One other thing regarding the source code—I use Telerik Silverlight Controls in my projects and this code sample assumes you have these installed. You can install them for free as a trial basis.

SQLDocuments.zip 
SQLDocuments_Tables.zip 

Thanks!
Chris Rouw, Far Reach Technologies MCTS Silverlight 4, Developer