Working with OData and WinJS ListView in Metro Application

In this post we will see how to consume Netflix OData feed in HTML based Metro Application. Movies information will be displayed as following. At the end of this post, we should have output as below,

image

Netflix exposed all movies information as OData and that is publicly available to use. Netflix OData feed of movies are available at following location

http://odata.netflix.com/Catalog/

Essentially we will pull movies information from Netflix and bind it to ListView Control of WinJS. We will start with creating a blank application.

image

In the code behind (default.js) define a variable of type WinJS List.

image

Now we need to fetch the movies detail from Netflix. For this we will use xhr function of WinJS. As the parameter of function, we will have to provide URL of the OData feed.

image

In above code snippet, we are performing following tasks

  • Making a call to Netflix OData using WinJS .xhr function
  • As input parameter to xhr function, we are passing exact url of OData endpoint.
  • We are applying projection and providing JSON format information in URL itself.
  • Once JSON data is fetched form Netflix server data is being parsed and pushed as individual items in the WinJS list.

As of now we do have data with us. Now let us go ahead and create a ListView control. You can create WinJS ListView as following. Put below code on the default.html

clip_image002

In above code we are simply creating a WinJS ListView and setting up some basic attributes like layout and itemTemplate. Now we need to create Item Template. Template is used to format data and controls how data will be displayed. Template can be created as following

image

In above code, we are binding data from the data source to different HTML element controls. At last in code behind we need to set the data source of ListView

image

Before you go ahead and run the application just put some CSS to make ListView more immersive. Put below CSS in default.css

image

Now go ahead and run the application. You should be getting the expected output as following

image

Let us consolidate all the codes from discussion.

Default.html

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8" />
 <title>testdemo</title>

<!-- WinJS references -->
 <link href="//Microsoft.WinJS.1.0.RC/css/ui-dark.css" rel="stylesheet" />
 <script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script>
 <script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script>

<!-- testdemo references -->
 <link href="/css/default.css" rel="stylesheet" />
 <script src="/js/default.js"></script>
</head>
<body>
 <h1>Netflix Movie Application</h1>
 <div id="moviesTemplate"
 data-win-control="WinJS.Binding.Template">
 <div style="width: 150px; height: 130px;">
 <img src="#" style="width: 100px; height: 100px;"
 data-win-bind="alt: title; src: picture" />
 <div>
 <h4 data-win-bind="innerText:title"></h4>
 </div>
 </div>
 </div>

<div id="movieListView"
 data-win-control="WinJS.UI.ListView"
 data-win-options="{itemTemplate : moviesTemplate,
 layout: {type: WinJS.UI.GridLayout} }">
 </div>

</body>
</html>

Code behind will have following codes

Default.js


// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
(function () {
 "use strict";

 var app = WinJS.Application;
 var activation = Windows.ApplicationModel.Activation;
 WinJS.strictProcessing();
 var movieArray = new WinJS.Binding.List();
 app.onactivated = function (args) {

 if (args.detail.kind === activation.ActivationKind.launch) {
 if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
 // TODO: This application has been newly launched. Initialize
 // your application here.
 } else {
 // TODO: This application has been reactivated from suspension.
 // Restore application state here.
 }
 args.setPromise(WinJS.UI.processAll());

 WinJS.xhr({
 url: "http://odata.netflix.com/Catalog/Titles" +
 "?$format=json&$select=ShortName,BoxArt&$top=300"
 }).then(function (xhr) {
 var movies = JSON.parse(xhr.response).d;
 movies.forEach(function (i) {
 movieArray.push({
 title: i.ShortName,
 picture: i.BoxArt.MediumUrl
 });
 });
 });
 var lstMovies = document.getElementById("movieListView").winControl;
 lstMovies.itemDataSource = movieArray.dataSource;

 }
 };

app.oncheckpoint = function (args) {

 };

app.start();
})();

And CSS will be as following

default.css


body {
}

@media screen and (-ms-view-state: fullscreen-landscape) {
}

@media screen and (-ms-view-state: filled) {
}

@media screen and (-ms-view-state: snapped) {
}

@media screen and (-ms-view-state: fullscreen-portrait) {
}
.win-listview
 {
 height: 100%;
 width: auto;

 }
 .win-listview .win-container {
 margin: 10px;
 }
 .win-listview .win-container:hover {
 background-color: red;
 border-color: red;
 }
 .semanticZoomItem
{
 width: 130px;
 height: 130px;
 background-color: rgba(38, 160, 218, 1.0);
}

.semanticZoomItem .semanticZoomItem-Text
 {
 padding: 10px;
 line-height: 150px;
 white-space: nowrap;
 color: white;
 }

In this way we can work with OData and winJS ListView. I hope you find this post useful. Thanks for reading.

How to create WCF Data Service with $JSONP format

In this post we will create WCF Data Service takes $JSONP in query and returns JSON data as response. For example if we want to fetch data as JSON we can fetch as following,

http://localhost:5157/WcfDataService1.svc/People?$format=json

To start with, Let us create WCF Data Service on School Database. Open Visual Studio 2010 as administrator and create a Web Application. We will be hosting WCF Data Service in web application.

image

Create DataModel

We will create DataModel using ADO.Net Entity framework. To add a DataModel we need to add ADO.Net Entity Model from Data Tab.

image

We want to create DataModel from database, so we will be choosing Generate from database option.

image

After this we need to choose Server name and database name. You can select appropriate authentication mechanism, in my case I am choosing Windows Authentication.

image

In last step, we need to select tables and views we want to keep as part of DataModel. In this case I am selecting all the tables.

image

Create WCF Data Service

To create WCF Data Service add new item selecting WCF Data Service project template from Web Tab

image

Modify WcfDataService.svc.cs as following. We need to provide DataModel name. In this case DataModel is SchoolEntites, we created in previous step.

image

By this step we have created WCF Data Service on SchoolEntities DataModel. Now press F5 to host created WCF Data Service in Cassini server and query in the browser.

image

And we can query a particular set of entity as following,

image

Enabling JSONP and URL Control Format

Read More Detail Here MSDN

If we want to fetch response in JSON format as following

http://localhost:5157/WcfDataService1.svc/People?$format=json

We will be getting following exception,

image

JSONP is used to fetch data from client side even though request need to be cross domain. To support $JSONP, we need to intercept the message before it gets dispatched. At intercept

  • Read the request URL and if $JSONP is there remove it from the querystring. Because reading $JSONP in connection string WCF Data Service runtime will throw exception as shown above.
  • And change Accept header to application/json

To enable this you need to add following file JSONPSupportBehavior.cs . Download sample project from and file from MSDN Code Gallery

image

Extract downloaded ZIP file and select JSONSupportBehavior.cs . Right click on your project and add existing item. Choose file JSONSupportBehavior.cs and add to the project.

image

Then modify WcfDataService.svc.cs as following,

image

We need to put JSONPSupportBehavior service attribute. Now go ahead and press F5 to run and fetch people in JSON format as following ,

http://localhost:5157/WcfDataService1.svc/People?$format=json

image

In this way we can enable $JSONP format on WCF Data Service. I hope this post is useful. Thanks for reading

 

How to work with Custom Method in WCF Data Service?

In this post we will see how could we expose a custom method in WCF Data Service? There are three steps involved in doing that

  1. Create a partial class of Entity class and add desired custom method in that.
  2. Add a method with WebGet attribute in service class. This method will make a call to the custom method added in partial entity class.
  3. At the client side call custom method using Execute method

Add Method in Partial Entity class

Create a partial class for entity class. If you are working on School database and your entity class name is SchoolEntities then add one more partial class along with custom method.



namespace WebApplication10
{
public partial class SchoolEntities
{
public string MyCustomMethod()
{
return "Hey I am returned from Custom Method ";
}

}
}

Modifying Service Class

Once you have added custom method in partial entity class, next you need to add method in service class (.svc) with WebGet attribute

image

Above function is creating instance of entity class and making a call to custom method. Custom method will be called at URL baseaddress/service.svc/CustomMethod

Putting all together service class with one custom method will be as below,


using System.Data.Services;
using System.Data.Services.Common;
using System.ServiceModel.Web;

namespace WebApplication10
{
public class WcfDataService1 : DataService<SchoolEntities>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{

config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}


[WebGet]
public string CustomMethod()
{
SchoolEntities entities = new SchoolEntities();
return entities.MyCustomMethod();
}



}
}


Calling custom method at client side

To call custom method at client side you need to make call to Execute method on instance of Entity class. Execute is a generic method and it takes return type of custom method as parameter. In this case return type of custom method is string. Execute method returns IEnuramble. As the parameter to Execute method you need to pass URI od custom method.

image

We can print returned value from custom method from WCF Data Service as below,


using System;
using ConsoleApplication32.ServiceReference1;

namespace ConsoleApplication32
{
class Program
{
static void Main(string[] args)
{
SchoolEntities entities = new SchoolEntities
(new Uri("http://localhost:2580/WcfDataService1.svc/"));
var result = entities.Execute<string>
(new Uri("http://localhost:2580/WcfDataService1.svc/CustomMethod"));

foreach (var r in result)
{
Console.WriteLine(r.ToString());
}
Console.ReadKey(true);


}
}
}


On running of above code you should be getting output as below,

clip_image002

In this way you can work with custom method in WCF Data service. I hope this post is useful. Thanks for reading.

Consuming ODATA in Silverlight 4.0

ODATA is everywhere and so is Silverlight. In this post, I will show, How ODATA can be consumed in Silverlight? “

OData URL

I will be using NorthWind OData URL. You can access that URL from below link.

http://services.odata.org/Northwind/Northwind.svc/

We are going to fetch Customers table from NorthWind DataBase.

Create Project and Add Service Reference

Create a Silverlight project

image

Choose Silverlight 4 as version

clip_image001

Right click on project and add Service Reference

In Address you need to give URL of OData. As we discussed in previous steps, here I am giving OData URL of NorthWind Database hosted by OData.org.

clip_image003

Add below namespaces on MainPage.Xaml.cs page

clip_image004

Please make sure about second namespace. Since, I have added service reference of OData with name ServiceReference1 and name of project is ODatainMangoUpdated.

Globally defined below variables

clip_image006

In constructor of MainPage,

  1. Create instance of NorthWindEntities
  2. Create instance of DataServiceCollection passing context
  3. Write the LINQ query.
  4. Attach event handler LoadCompleted on DataServiceCollection object.
  5. Fetch the result asynchronously

image

On the completed event

  1. Check whether next page exist or not , if yes load automatically
  2. Set the DataContext of layout as result.

image

Design Page and Bind List Box

Here you need to create a ListBox and in Data Template put three TextBlock vertically. Bind the different columns of table to the text blocks

image

For your reference full source codes are given below. Feel free to use them Smile

MainPage.Xaml


<UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"  x:Class="ODATAWithSilverLight.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"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White">
        <ListBox x:Name="MainListBox" Margin="0,0,-12,0"
                 ItemsSource="{Binding}"
                 Height="350"
                 Width="250"
                 ScrollViewer.VerticalScrollBarVisibility="Visible">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="0,0,0,17" Width="432">
                        <TextBlock Text="{Binding Path=CompanyName}"
                                          TextWrapping="NoWrap"
                                       />
                        <TextBlock Text="{Binding Path=ContactName}"
                                         TextWrapping="NoWrap"
                                       Margin="12,-6,12,0" />
                        <TextBlock Text="{Binding Path=Phone}"
                                          TextWrapping="NoWrap"
                                       Margin="12,-6,12,0"
                                       />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

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 ODATAWithSilverLight.ServiceReference1;
using System.Data.Services.Client;

namespace ODATAWithSilverLight
{
    public partial class MainPage : UserControl
    {

        private NorthwindEntities context;
        private readonly Uri ODataUri = new Uri("http://services.odata.org/Northwind/Northwind.svc/");
        private DataServiceCollection<Customer> lstCustomers;

        public MainPage()
        {
            InitializeComponent();
            context = new NorthwindEntities(ODataUri);

            lstCustomers = new DataServiceCollection<Customer>(context);
            var result = from r in context.Customers select r;
            lstCustomers.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(lstCustomers_LoadCompleted);
            lstCustomers.LoadAsync(result);

        }

        void lstCustomers_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
            if (lstCustomers.Continuation != null)
            {
                lstCustomers.LoadNextPartialSetAsync();
            }
            else
            {
                this.LayoutRoot.DataContext = lstCustomers;
            }

        }

    }
}

Run Application

Press F5 to run the application. You should get all the records from Customer table in List box.

image

I Hope this post was useful. Thanks for reading Smile



********************

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine