Procedura: accedere a dati binari come flusso (client Silverlight)
OData (Open Data Protocol) consente a un servizio dati di rendere disponibili i dati binari all'esterno del feed stesso. Questi dati binari, chiamati risorsa multimediale, sono separati, ma correlati, a un'entità, chiamata voce di collegamento multimediale. Per ulteriori informazioni, vedere Utilizzo di dati binari (WCF Data Services).
La procedura e gli esempi di questo argomento illustrano in che modo aggiungere un riferimento al servizio dati di flusso Northwind di esempio e chiamare il metodo GetReadStream per recuperare dati binari come flusso da un servizio OData.
Il servizio dati di flusso a cui accede l'applicazione è una versione speciale del servizio dati Northwind di esempio modificato per il supporto dei flussi. Per ulteriori informazioni, vedere Provider di flusso (WCF Data Services). È possibile scaricare il servizio dati di flusso Northwind di esempio dal sito Web di MSDN Code Gallery.
Nota
Se il dominio del servizio dati di flusso Northwind è diverso dal dominio dell'esempio illustrato in questo argomento, è necessario abilitare le comunicazioni tra domini mediante uno specifico file di criteri.Per ulteriori informazioni, vedere HTTP Communication and Security with Silverlight.
Per aggiungere un riferimento al servizio dati di flusso Northwind di esempio
Scaricare il servizio dati di flusso Northwind di esempio dal sito Web di MSDN Code Gallery e seguire le istruzioni nel file readme di esempio per distribuire il servizio in IIS.
Fare clic con il pulsante destro del mouse sul progetto Silverlight, quindi scegliere Aggiungi riferimento al servizio.
Nella casella di testo Indirizzo digitare l'URI per il servizio dati di flusso Northwind distribuito, quindi fare clic su Vai.
Nella casella di testo Spazio dei nomi digitare NorthwindStreaming, quindi scegliere OK.
Verrà aggiunto un nuovo file di codice al progetto, che contiene le classi di dati utilizzate per accedere e interagire con le risorse del servizio dati come oggetti.
Esempio
L'esempio seguente è tratto dalla pagina code-behind di una pagina XAML (Extensible Application Markup Language) che rappresenta l'applicazione StreamingClient per Silverlight. Quando la pagina viene caricata, viene creato un oggetto DataServiceCollection<T> in base al risultato di una query che restituisce tutti i dipendenti. Se si seleziona un dipendente, il metodo BeginGetReadStream viene chiamato nell'istanza DataServiceContext. Al termine della chiamata asincrona, verrà chiamato il gestore OnGetReadStreamComplete. In questo metodo il dispatcher viene utilizzato per richiamare il metodo EndGetReadStream e sarà possibile accedere al flusso di dati binari dall'oggetto DataServiceStreamResponse.
Imports System
Imports System.Linq
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.Windows.Media.Imaging
Imports StreamingClient.NorthwindStreaming
Imports System.Data.Services.Client
Imports System.IO
Partial Public Class MainPage
Inherits UserControl
Private context As NorthwindEntities
Private trackedEmployees As DataServiceCollection(Of Employees)
Private currentEmployee As Employees
Private imageSource As BitmapImage
Private currentResult As IAsyncResult
' Replace with the URI of your NorthwindStreaming service implementation.
Private svcUri As String = _
"https://localhost/NorthwindStreaming/NorthwindStreaming.svc"
Public Sub New()
InitializeComponent()
End Sub
Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Instantiate the data service context.
context = New NorthwindEntities(New Uri(svcUri))
' Define a LINQ query for Employees.
Dim query = From employees In context.Employees _
Select employees
Try
' Create a new collection for binding all employees.
trackedEmployees = New DataServiceCollection(Of Employees)()
' Define a handler for the LoadCompleted event of the binding collection.
AddHandler trackedEmployees.LoadCompleted, _
AddressOf trackedEmployees_LoadCompleted
' Execute the query asynchronously and
' load the results into the collection.
trackedEmployees.LoadAsync(query)
Catch ex As InvalidOperationException
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub trackedEmployees_LoadCompleted(ByVal sender As Object, ByVal e As LoadCompletedEventArgs)
If e.Error Is Nothing Then
' Load all pages of Orders before binding.
If trackedEmployees.Continuation IsNot Nothing Then
' 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 Then
MessageBox.Show("Data could not be returned from the data service.")
End If
' Select the first employee in the collection.
employeesComboBox.SelectedIndex = 0
End If
Else
MessageBox.Show(String.Format("An error has occured: {0}", e.Error.Message))
End If
End Sub
Private Sub employeesComboBox_SelectionChanged(ByVal sender As Object, ByVal e As SelectionChangedEventArgs)
' Define the method to call when the asynchronous method completes.
Dim callback As AsyncCallback = AddressOf OnGetReadStreamComplete
' Get the currently selected employee.
currentEmployee = _
CType(Me.employeesComboBox.SelectedItem, Employees)
' Set the Accept header to the jpeg image content type.
Dim 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, _
callback, context)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub OnGetReadStreamComplete(ByVal result As IAsyncResult)
' Persist the context from the result.
currentResult = result
' Use the Dispatcher to ensure that the
' asynchronous call returns in the correct thread.
Dispatcher.BeginInvoke(AddressOf OnGetReadStreamCompleteByDispatcher)
End Sub
Private Sub OnGetReadStreamCompleteByDispatcher()
' Use the Dispatcher to ensure that the
' asynchronous call returns in the correct thread.
' Get the original context back from the result.
context = CType(currentResult.AsyncState, NorthwindEntities)
Try
' Get the response from the returned context.
Dim response =
context.EndGetReadStream(currentResult)
Using imageStream As MemoryStream = _
New MemoryStream()
Dim buffer = New Byte(1000) {}
Dim count = 0
' Read the returned stream into the new memory stream.
If response.Stream.CanRead Then
Do
count = response.Stream.Read(buffer, 0, buffer.Length)
imageStream.Write(buffer, 0, count)
Loop While 0 < count
End If
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
End Using
Catch ex As DataServiceRequestException
MessageBox.Show(ex.InnerException.Message)
Catch ex As Exception
MessageBox.Show( _
String.Format("The requested image for employee '{0}' is not valid.", _
currentEmployee.LastName))
End Try
End Sub
End Class
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 =
"https://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));
}
}
);
}
}
}
Nel codice XAML seguente viene definita la pagina per l'esempio precedente.
<UserControl x:Class="StreamingClient.MainPage"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://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>