Export (0) Print
Expand All

How to: Access Binary Data as a Stream (WCF Data Services/Silverlight)

Open Data Protocol (OData) enables a data service to make binary data available outside of the feed itself. This binary data, called a media resource, is separate from but related to an entity, which is called a media link entry. For more information, see Working with Binary Data (WCF Data Services).

The procedure and examples in this topic show you how to add a reference to the Northwind streaming sample data service and call the GetReadStream(Object) method to retrieve binary data as a stream from an OData service. 

The streaming data service accessed by the application is a special version of the Northwind sample data service that has been modified to support streaming. For more information see Streaming Provider (WCF Data Services). The Northwind streaming data service sample can be downloaded from the MSDN Code Gallery Web site.

Note Note:

When the domain of the Northwind streaming data service is different from the domain of the sample shown in this topic, you must enable cross-domain communication by using a cross-domain policy file. For more information, see HTTP Communication and Security with Silverlight.

To add a reference to the Northwind streaming data service sample

  1. Download the Northwind streaming data service sample from the MSDN Code Gallery Web site and follow the instructions in the sample readme file to deploy the service on IIS.

  2. Right-click the Silverlight project and click Add Service Reference

  3. In the Address text box, type the URI for the deployed Northwind streaming data service and then click Go.

  4. In the Namespace text box, type NorthwindStreaming, and then click OK.

    This adds a new code file to the project, which contains the data classes that are used to access and interact with data service resources as objects.

The following example is from the code-behind page for an Extensible Application Markup Language (XAML) page that is the StreamingClient application for Silverlight. When the page is loaded, a DataServiceCollection<T> is created based on the result of a query that returns all employees. When an employee is selected, the BeginGetReadStream method is called on the DataServiceContext instance. When the asynchronous call completes, the OnGetReadStreamComplete handler is called. In this method, the dispatcher is used to invoke the EndGetReadStream method and the binary stream is accessed from the DataServiceStreamResponse object. 


using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using StreamingClient.NorthwindStreaming;
using System.Data.Services.Client;
using System.IO;

namespace StreamingClient
{
    public partial class MainPage : UserControl
    {

        private NorthwindEntities context;
        private DataServiceCollection<Employees> trackedEmployees;
        private Employees currentEmployee;
        private BitmapImage imageSource;

        // Replace with the URI of your NorthwindStreaming service implementation.
        private string svcUri =
            "http://localhost/NorthwindStreaming/NorthwindStreaming.svc";

        public MainPage()
        {
            InitializeComponent();
        }


        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Instantiate the data service context.
            context = new NorthwindEntities(new Uri(svcUri));

            // Define a LINQ query for Employees.
            var query = from employees in context.Employees
                        select employees;

            try
            {
                // Create a new collection for binding all employees.
                trackedEmployees = new DataServiceCollection<Employees>();

                // Define a handler for the LoadCompleted event of the binding collection.
                trackedEmployees.LoadCompleted +=
                    new EventHandler<LoadCompletedEventArgs>(trackedEmployees_LoadCompleted);

                // Execute the query asynchronously and 
                // load the results into the collection.
                trackedEmployees.LoadAsync(query);

            }
            catch (InvalidOperationException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        private void trackedEmployees_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                // Load all pages of Orders before binding.
                if (trackedEmployees.Continuation != null)
                {
                    // Load the next page of results.
                    trackedEmployees.LoadNextPartialSetAsync();
                }
                else
                {
                    // Bind the root StackPanel element to the collection;
                    // related object binding paths are defined in the XAML.
                    LayoutRoot.DataContext = trackedEmployees;

                    if (trackedEmployees.Count == 0)
                    {
                        MessageBox.Show("Data could not be returned from the data service.");
                    }

                    // Select the first employee in the collection.
                    employeesComboBox.SelectedIndex = 0;
                }
            }
            else
            {
                MessageBox.Show(string.Format("An error has occured: {0}", e.Error.Message));
            }
        }

        private void employeesComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Get the currently selected employee.
            currentEmployee =
                (Employees)this.employeesComboBox.SelectedItem;

            // Set the Accept header to the jpeg image content type.
            DataServiceRequestArgs requestArgs = new DataServiceRequestArgs();
            requestArgs.AcceptContentType = "image/jpeg";

            try
            {
                // Start to get the read stream for the media resource for the 
                // currently selected media link entry.    
                context.BeginGetReadStream(currentEmployee, requestArgs, 
                    OnGetReadStreamComplete, context);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void OnGetReadStreamComplete(IAsyncResult result)
        {
            // Use the Dispatcher to ensure that the 
            // asynchronous call returns in the correct thread.
            Dispatcher.BeginInvoke(() =>
                {
                    // Get the original context back from the result.
                    context =
                        result.AsyncState as NorthwindEntities;

                    try
                    {
                        // Get the response from the returned context.
                        DataServiceStreamResponse response = 
                            context.EndGetReadStream(result);

                        using (MemoryStream imageStream =
                            new MemoryStream())
                        {
                            byte[] buffer = new byte[1000];
                            int count = 0;

                            // Read the returned stream into the new memory stream.
                            while (response.Stream.CanRead && (0 < (
                                count = response.Stream.Read(buffer, 0, buffer.Length))))
                            {
                                imageStream.Write(buffer, 0, count);
                            }

                            imageStream.Position = 0;

                            // Use the returned bitmap stream to create a bitmap image that is 
                            // the source of the image control.
                            imageSource = new BitmapImage() ;
                            imageSource.SetSource(imageStream);
                            employeeImage.Source = imageSource;
                        }
                    }
                    catch (DataServiceRequestException ex)
                    {
                        MessageBox.Show(ex.InnerException.Message);
                    }
                    catch (Exception)
                    {
                        MessageBox.Show(
                            string.Format("The requested image for employee '{0}' is not valid.",
                            currentEmployee.LastName));
                    }
                }
            );
        }
    }
}


The following XAML defines the page for the previous example.


<UserControl x:Class="StreamingClient.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" Height="300" Width="400" Loaded="Window_Loaded">
    <Grid Name="LayoutRoot" >
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Width="Auto" VerticalAlignment="Bottom" Height="50" Margin="0,0,0,250">
            <ComboBox Height="23" Name="employeesComboBox" Margin="50,12,0,12" Width="200" DisplayMemberPath="LastName" ItemsSource="{Binding}" SelectionChanged="employeesComboBox_SelectionChanged" />
        </StackPanel>
        <Image Margin="12,76,12,26" Name="employeeImage" Width="350" Stretch="Fill"/>
    </Grid>
</UserControl>


Community Additions

ADD
Show:
© 2014 Microsoft