Working with Binary Data (WCF Data Services)

The WCF Data Services client library enables you to retrieve and update binary data from an Open Data Protocol (OData) feed in one of the following ways:

  • As a primitive type property of an entity. This is the recommended method for working with small binary data objects that can be easily loaded into memory. In this case, the binary property is an entity property exposed by the data model, and the data service serializes the binary data as base-64 binary encoded XML in the response message.

  • As a separate binary resource stream. This is the recommended method for accessing and changing binary large object (BLOB) data that may represent a photo, video, or any other type of binary encoded data.

WCF Data Services implements the streaming of binary data by using HTTP as defined in the OData protocol. OData provides the following streaming mechanisms to associate binary data with an entity:

  • Media resource/media link entry

    The Atom Publishing Protocol (AtomPub) defines a mechanism to associate binary data as a media resource with an entry in a data feed, which is called the media link entry. There can only be one media resource defined for a given media link entry. A media resource can be considered as the default stream for an entity. OData inherits this streaming behavior from AtomPub.

  • Named resource stream

    Starting with version 3 of OData, an entity can have multiple related resource streams, which are accessed by name. This mechanism does not depend on AtomPub, so it is possible for an entity to have named resource streams and not be a media link entry. It is also possible for a media link entry to have named streams. For more information, see Streaming Provider (WCF Data Services).

Entity Metadata

An entity that has related binary resource streams is indicated in the data service metadata in one of the following ways, depending on the type of stream:

  1. Media resource:

    By the HasStream attribute an entity type that is the media link entry.

  2. Named resource stream:

    By one or more properties of an entity in the data model that are of the Stream data type.

    Support for the Stream data type in the data model requires version 2.2 of the EDM. For more information, see Streaming Provider (WCF Data Services).

In the following example, the PhotoInfo entity is a media link entry that has both a related media resource, indicated by the HasStream attribute, and a named resource stream, named Thumbnail.

<EntityType Name="PhotoInfo" m:HasStream="true">
  <Key>
    <PropertyRef Name="PhotoId" />
  </Key>
  <Property Name="PhotoId" Type="Edm.Int32" Nullable="false" 
            p9:StoreGeneratedPattern="Identity" 
            xmlns:p9="https://schemas.microsoft.com/ado/2009/02/edm/annotation" />
  <Property Name="FileName" Type="Edm.String" Nullable="false" />
  <Property Name="FileSize" Type="Edm.Int32" Nullable="true" />
  <Property Name="DateTaken" Type="Edm.DateTime" Nullable="true" />
  <Property Name="TakenBy" Type="Edm.String" Nullable="true" />
  <Property Name="DateAdded" Type="Edm.DateTime" Nullable="false" />
  <Property Name="Exposure" Type="PhotoData.Exposure" Nullable="false" />
  <Property Name="Dimensions" Type="PhotoData.Dimensions" Nullable="false" />
  <Property Name="DateModified" Type="Edm.DateTime" Nullable="false" />
  <Property Name="Comments" Type="Edm.String" Nullable="true" MaxLength="Max" 
            Unicode="true" FixedLength="false" />
  <Property Name="ContentType" Type="Edm.String" Nullable="true" MaxLength="50" 
            Unicode="true" FixedLength="false" />
  <Property Name="Thumbnail" Type="Edm.Stream" Nullable="false" />
</EntityType>

The remaining examples in this topic show how to access and change the media resource stream. For a complete example of how to consume a media resource stream in a .NET Framework client application by using the WCF Data Services client library, see the post Accessing a Media Resource Stream from the Client.

Accessing Binary Resource Streams

The WCF Data Services client library provides methods for accessing binary resource streams from an OData-based data service. When downloading a media resource, you can either use the URI of the media resource or you can get a binary stream that contains the media resource data itself. You can also upload media resource data as a binary stream.

Tip

For a step-by-step example of how to create a Windows Presentation Foundation (WPF) client application that downloads binary image files from an OData service that stores photos, see the post Data Services Streaming Provider Series-Part 2: Accessing a Media Resource Stream from the Client. To download the sample code for the stream photo data service featured in the blog post, see the Streaming Photo Data Service Sample in MSDN Code Gallery.

Getting the URI of the Binary Stream

When retrieving certain types of media resources, such as images and other media files, it is often easier to use the URI of the media resource in your application than handling the binary data stream itself. To get the URI of a resource stream associated with a give media link entry, you must call the GetReadStreamUri(Object) method on the DataServiceContext instance that is tracking the entity. To get the URI of a named resource stream, call the method overload that takes a name parameter, which is the name of the stream. The following example shows how to call the GetReadStreamUri(Object) method to get the URI of a media resource stream that is used to create a new image on the client:

' Use the ReadStreamUri of the Media Resource for selected PhotoInfo object
' as the URI source of a new bitmap image.
photoImage.Source = New BitmapImage(context.GetReadStreamUri(currentPhoto))
// Use the ReadStreamUri of the Media Resource for selected PhotoInfo object
// as the URI source of a new bitmap image.
photoImage.Source = new BitmapImage(context.GetReadStreamUri(currentPhoto));

For named resource streams, you can also get the URI of the stream directly from the stream property. For each property of the media link entry returned by the data service metadata that is of a Stream type, in the data service tools generate a property that returns a DataServiceStreamLink instance. The Uri property of this DataServiceStreamLink is the URI of the named resource stream. This enables you to get the URI directly from the media link entry object or as the result of a language integrated query (LINQ).

Downloading the Binary Resource Stream

When retrieving a binary resource stream, you must call the GetReadStream method on the DataServiceContext instance that is tracking the media link entry. This method sends a request to the data service that returns a DataServiceStreamResponse object, which has a reference to the stream that contains the resource. Use this method when your application requires the binary resource as a Stream. When accessing a named resource stream, call the method overload that takes a name parameter, which is the name of the resource stream. The following example shows how to call the GetReadStream method to retrieve a stream that is used to create a new image on the client:

' Get the read stream for the Media Resource of the currently selected 
' entity (Media Link Entry).
Using response As DataServiceStreamResponse = _
        context.GetReadStream(currentEmployee, "image/bmp")

    ' Use the returned binary stream to create a bitmap image that is 
    ' the source of the image control.
    employeeImage.Source = CreateBitmapFromStream(response.Stream)
End Using
// Get the read stream for the Media Resource of the currently selected 
// entity (Media Link Entry).
using (DataServiceStreamResponse response =
    context.GetReadStream(currentEmployee, "image/bmp"))
{
    // Use the returned binary stream to create a bitmap image that is 
    // the source of the image control.
    employeeImage.Source = CreateBitmapFromStream(response.Stream);
}

Note

The Content-Length header in the response message that contains the binary steam is not set by the data service. This value may not reflect the actual length of the binary data stream.

Uploading a Media Resource as a Stream

To insert or update a media resource, call the SetSaveStream method on the DataServiceContext instance that is tracking the entity. This method sends a request to the data service that contains the media resource read from the supplied stream. When uploading a named resource stream, call the method overload that takes a name parameter, which is the name of the resource stream. The following example shows how to call the SetSaveStream method to send a bitmap image that belongs to a specific employee to the data service:

' Set the file stream as the source of binary stream 
' to send to the data service. The Slug header is the file name and
' the content type is determined from the file extension. 
' A value of 'true' means that the stream is closed by the client when 
' the upload is complete.
context.SetSaveStream(photoEntity, imageStream, True, _
    photoEntity.ContentType, photoEntity.FileName)
// Set the file stream as the source of binary stream 
// to send to the data service. The Slug header is the file name and
// the content type is determined from the file extension. 
// A value of 'true' means that the stream is closed by the client when 
// the upload is complete.
context.SetSaveStream(photoEntity, imageStream, true,
    photoEntity.ContentType, photoEntity.FileName);

In this example, the SetSaveStream method is called by supplying a value of true for the closeStream parameter. This guarantees that the DataServiceContext closes the stream after the binary data is uploaded to the data service.

Note

When you call SetSaveStream(Object, String, Stream, Boolean, String), the stream is not sent to the data service until SaveChanges is called.

See Also

Concepts

Binding Data to Controls (WCF Data Services)

Other Resources

Data Client (WCF Data Services)