Reader Level:
ARTICLE

Picture Gallery for Windows 7 Phone using WCF REST Service

Posted by Dhananjay Kumar Articles | Windows Phone April 27, 2010
In this article I will give you walkthrough of creating a Picture Gallery for Windows 7 phone.
  • 0
  • 0
  • 17522
Download Files:
 

Objective 

In this article I will give you walkthrough of creating a Picture Gallery for Windows 7 phone. I will show how to fetch images from server using WCF REST service.

The final output would be like below 

1.gif


How to use attached ZIP File of the source code 
  1. Download and unzip it.  And make sure you have Image folder in your local D drive and put some images inside Images folder.
  2. Open the Service folder and right click the solution and run as an administrator. 
  3. Once solution is open in visual studio right click on service1.svc and select view in browser
  4. You will get End point not found in browser. Append GetFilesname  in the address bar with URL. You should get list of files name in browser as we are getting in Step 4. Copy the URL and replace this in Button click event of Mainpage.Xaml.cs of Phone application. 
  5. In the same way modify the URL in changed event of combo box. 
  6. Open Client folder and open the solution and do the 4th and 5th step changes. You are all set to go. 
Please read this article before going through this article.

In this article, majorly I am going to show you two things 
  1. How could we process image from file system of server using REST service and return the jpeg format as response. 
  2. How could we consume REST service in Windows 7 phone application?  And how could we de- serialize stream at in windows 7 phone application. 
Working Diagram 

 2.gif

If you see above diagram, we are going to perform below steps.
  1. Image files are at some certain location of server.
  2. Using .Net file handling classes, we will fetch those image files. 
  3. Using WCF REST service we will return image in form of stream.
  4. We will test the REST service in browser. 
  5. We will consume the REST service in Windows 7 phone application. 
Step 1

On your server or hard disk of your development machine put some images in a particular folder of a particular drive.  I am putting some images inside IMAGES folder of D drive.

I do have below images inside D:\Images folder

3.gif

Step 2

Accessing the File System in service

To access the files and work with file system in .Net we need to add namespace System.IO .

Now if we want to access name of all the files inside a particular folder, we need to access all the files using instance of DirectoryInfo class.  So the code to return all the file names is as below, 

4.gif

In above code 
  1. I am creating instance of List of string. 
  2. I am creating instance of DirectoryInfo class. In constructor, I am passing the location of the directory. 
  3. Using GetFiles method of DirectoryInfo class, I am fetching all the files in that particular directory.
  4. I am iterating through FileInfo array and fetching name of all the files. 
  5. I am splitting the file name over dot(.) because I do not want extension of the file to be added as file name. 
  6. Finally I am adding the file names in list of string and returning it. 
Step 3

In this step, I will create a WCF REST Service. This Service will return Files name and images as stream.  So to create WCF REST Service follows below steps 

Step 3A

Create a WCF application.  To create a new application File -> New -> Web-> WCF Service Application.

5.gif
 
Step 3B

Remove all the default code created by WCF. Remove code from IService 1 interface and Service1 class.  Remove the code from Web.Config also. Open Web.Config and remove System.Servicemodel codes. 

Step 3C

Right click on Service1.svc select View markup and add below code 

6.gif

<%@ ServiceHost Language="C#" Debug="true" Service="FetchingImageinBrowser.Service1" CodeBehind="Service1.svc.cs" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Step 3D

Now I will create Contracts. There would be two service methods.  One would be returning FilesName and other would be returning Stream.  

7.gif
 
If you see the above Service Contract, you will find 
  1. GetImage   operation contract is taking file name as input parameter and returning stream.  This service method will be accessed through default URI of hosting server slashed with GetImageand then slashed with input parameter. 

    http://localhost:53767/Service1.svc/GetImage/MyImage

  2. GetFIlesName operation contract is returning all the files name of a particular directory.  This service method will be accessed through below URL.

    http://localhost:53767/Service1.svc/GetFilesName
In both above case service is hosted on local server on the port 53767.

Step 3E

In this method we will define the service. Already in step 2 I have shown you, how we could fetch name of all the files from a particular directory.  The other service method returning stream is below.

8.gif
 
If you read the above code, I am opening the input file in FileStream. Then using WebOperationContext class, I am setting the Outgoing response as Image and Jpeg. 

For your reference, the full source code for the service is as below 

Contract (IService1.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.IO ;
namespace FetchingImageinBrowser
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebGet(UriTemplate = "GetImage/{imageName}",
            RequestFormat = WebMessageFormat.Xml,
            ResponseFormat = WebMessageFormat.Xml)]
        Stream GetImage(string imageName);
         [OperationContract]
        [WebGet(UriTemplate = "GetFilesName")]
        List<String> GetFilesName();
    }  
}

Service Definition (Service1.svc.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.IO ;
namespace FetchingImageinBrowser
{
    public class Service1 : IService1
    {
        public Stream GetImage(string imageName)
        {
            FileStream fs = null;
            string fileName = string.Format(@"D:\Images\{0}.jpg", imageName);
            fs = File.OpenRead(fileName);
            WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
            return fs;
        }
        public List<String> GetFilesName()
        {
            List<String> lstFileName = new List<string>();
            DirectoryInfo dir = new DirectoryInfo(@"D:\Images");
            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo f in files)
            {
                lstFileName.Add(f.Name.Split(".".ToCharArray())[0]);
            }
            return lstFileName;
        }
    }
}

Step 4

Run the service. By default service will be hosted in Cassini server.   We can test this service in browser because it is REST service.  

When you run URL   http://localhost:53767/Service1.svc/GetFilesName  , You will get below output. All the files inside the folder is listed in the browser.

9.gif
 
When you run URL http://localhost:53767/Service1.svc/GetImage/MyImage, you will get MYImage (name of the image file) in browser like below 

10.gif
 
So far, we have created the service and tested successfully in the browser. So we are all set to consume the service in Windows 7 Phone application. 

Step 5

Since service is up and running, now we can consume the service anywhere. In this tutorial we are going to consume the service in Windows 7 Phone application. 

11.gif

Step 5A

Create a new Windows Phone Application.  From Silverlight for Windows Phone tab select Windows Phone Application project type. 

12.gif
 
Step 5B

In this step, we will design the page.  

13.gif
  1. I have divided the Content Grid in two rows with the ratio of 3:1
  2. In first row put a stack panel. 
  3. Inside stack panel put a Button and a Combo box. 
  4. Register selection changed event with Combo box. 
  5. In second row put a Image control. 
  6. Set the height and width of the image as Auto. 
Step 5C

In this step we will write the code behind to consume the service. 

On click event of button, we will call the service and get the entire files name inside the particular directory. 

14.gif
  1. In above code, I am using WebClient to do asynchronous call to REST service. 
  2. If you see closely in string I am assigning the same URL we tested in step 4 to fetch file names.
  3. Using DataContractSerializer class we are creating an instance and passing type we are going to de serialize in constructor. 
  4. We are reading all the objects in instance of DataContractSerializer and explicitly typecasting it to List<String>.
  5. One by one we are iterating to list and adding each filename (string) as item of combo box.
On changed event of combo box, we will pass the image name as selected item in combo box and fetch the image and set that image as source of image control.  

15.gif
  1. In above code, I am using WebClient to do asynchronous call to REST service. 
  2. If you see closely in string I am assigning the same URL we tested in step 4 to fetch particular image.
  3. I am creating instance of BitmapImage.
  4. Setting the source of the image as response from the service. 
  5. Setting the source of image control as instance of BitmapImage. 
For your reference whole source code is as below, 

MainPage.Xaml

<phoneNavigation:PhoneApplicationPage
    x:Class="RESTServiceConsuming.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}">
    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>      
        <Grid x:Name="TitleGrid" Grid.Row="0">
            <TextBlock Text="Windows 7 Phone" x:Name="textBlockPageTitle" Style="{StaticResource PhoneTextPageTitle1Style}"/>
            <TextBlock Text="Picture Gallery" x:Name="textBlockListTitle" Style="{StaticResource PhoneTextPageTitle2Style}"/>
        </Grid>      
        <Grid x:Name="ContentGrid" Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="3*" />
            </Grid.RowDefinitions>
            <StackPanel Orientation="Horizontal" Margin="0,0,0,31">              
                <Button x:Name="myButton" Height="50" Content="Get FileNames" />           
                <ComboBox x:Name="cmbName" Height="50"
                          SelectionChanged="cmbName_SelectionChanged"
                          Margin="21,0,10,0"
                          Foreground="Black" Width="211" />
            </StackPanel>
            <Image Grid.Row="1" x:Name="myImage"
                   Height="Auto" Width="Auto"
                   ScrollViewer.HorizontalScrollBarVisibility="Auto"
                   ScrollViewer.VerticalScrollBarVisibility="Auto" />         
        </Grid>
    </Grid>  
</phoneNavigation:PhoneApplicationPage>

MainPage.Xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Xml;
using System.Runtime.Serialization;
using System.Windows.Media.Imaging;

namespace RESTServiceConsuming
{
    public partial class MainPage : PhoneApplicationPage
    {
        public MainPage()
        {
            InitializeComponent();
            SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
            myButton.Click += new RoutedEventHandler(myButton_Click);  
        }
        void myButton_Click(object sender, RoutedEventArgs e)
        {
            cmbName.Items.Clear();
            cmbName.SelectedIndex = -1;
            string strUriFilesName = "http://localhost:53767/Service1.svc/getfilesName";
            WebClient proxy1 = new WebClient();
            proxy1.OpenReadCompleted += new OpenReadCompletedEventHandler(proxy1_OpenReadCompleted);
            proxy1.OpenReadAsync(new Uri(strUriFilesName));
        }
        void proxy1_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            DataContractSerializer ds = new DataContractSerializer(typeof(List<string>));
            List<string> lstFileName = (List<string>) ds.ReadObject(e.Result);
            foreach (string file in lstFileName)
            {
                cmbName.Items.Add(file);
            }
        }
        private void cmbName_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (cmbName.SelectedIndex != -1)
            {
                string imageName = cmbName.SelectedItem.ToString();
                WebClient proxy = new WebClient();
                string strUriImage = "http://localhost:53767/Service1.svc/getImage/" + imageName;
                proxy.OpenReadCompleted += new OpenReadCompletedEventHandler(proxy_OpenReadCompleted);
                proxy.OpenReadAsync(new Uri(strUriImage));
            }
        }
        void proxy_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            BitmapImage img = new BitmapImage();
            img.SetSource(e.Result);
            myImage.Source = img;
        }
    }
}

Now we are ready to run our application.  Press F5 and run the application in emulator.  After running you will get first screen. Press button to populate the entire files name in the combo box.  After selecting a particular file that image would get display as third screen. 

16.gif
 
I hope this article was informative. Happy Coding.