Consuming "Dallas" OData with Managed Code

This topic describes how to consume data from “Dallas” with an OData endpoint in applications using managed code.

Introduction

“Dallas” is in its third Community Technology Preview (CTP). CTP3 introduces live OData services. To learn more about the differences between CTP3 OData based services and CTP2 based services visit the “Dallas” team blog.

Accessing “Dallas” OData requires adding a “service reference” to your Visual Studio project. Service references are specific to particular datasets. The code in a service reference should not be modified as modification could result in improper functioning and side effects. Additionally, modifications will be overwritten whenever your service reference is refreshed. If accessing multiple data sources you need to add a service reference for each data source.

Prerequisites

This section assumes that you have a “Dallas” account and have completed Lessons 1 through 3 in the section Working with "Dallas" Accounts and Subscriptions and are familiar with the “Dallas” Marketplace and Service Explorer. You also need a subscription to InfoGroup’s InfoUSA New, Out-Of-Business and Historical Businesses - InfoUSA CTP3 service.

Step 1: Starting Your Project

  1. Start Visual Studio as an Administrator

    1. Right click Visual Studio in your Start Menu and select Run as administrator.

    2. When asked if you want to allow this program (devenv.exe) to make changes to your computer click Yes.

  2. On the Visual Studio Start Page select New Project.

  3. From the New Project dialog box select C# Console Application. Give your project a meaningful name. For example, for this project you could name it InfoUSABusinessData. Then click OK.

  4. Add the following using statement to Program.cs.

    
    Imports System.Net ' needed for authentication
    
    

Step 2: Adding a Service Reference to Your Application

After starting Visual Studio as an administrator and creating a new console application (Step 1) add the service reference for the data you want to consume.

  1. Sign in to your Windows Live Id.

  2. Get the URL for the service you want to use.

    1. Go to the “Dallas” Marketplace and select the Subscriptions tab.

    2. Find the InfoUSA New, Out-Of-Business and Historical Businesses - InfoUSA service and click Click here to explore the dataset.

    3. Scroll to the bottom of the page and find the text Create client classes by adding a service reference in Microsoft Visual Studio. Copy the link below it to your clipboard.

      Service Reference URL

  3. Add a service reference to your Visual Studio project

    1. Return to your Visual Studio project. In Solution Explorer right click References. Select Add Service Reference… from the dropdown menu.

      WarningWarning
      This only works in Microsoft® Visual Studio.

      Add Service Reference in Visual Studio

    2. Paste the URL you copied to your clipboard above into the Address dropdown. Click Go. Wait a few moments for the Services text box to populate with the services available to your project.

    3. Click the Namespace: textbox. Give it a meaningful namespace name. For example, InfoUSABusinesses. Click OK.

      This adds a Service Reference node to your project in Solution Explorer with this service reference under it.

      In the image below the red oval is the URL you pasted in for your service, the blue oval is the name of the service available at this URL, and the green oval is the namespace name you create.

      Visual Studio Service Reference Dialog
  4. Add the service reference to your code.

    1. Open Program.cs in the Visual Studio code window.

    2. Add the following using statement which makes your service reference accessible to your application.

      Author's Note: InfoUSABusinessData is the name you chose as your project name/namespace. InfoUSABusinesses is the namespace name you chose when you added the service reference.

      
      Imports InfoUSABusinessData.InfoUSABusinesses ' RESTful proxy to data
      
      

Step 3: Consuming OData with Managed Code

  1. Within your project’s namespace create a public class, GetBusinessData. This class consumes the business data from the InfoUSA New, Out-of-Business and Historical Bussinesses – InfoUSA service.

  2. Create two private variables for your class.

    1. A Uri to the service and a service container that stores your credentials in service context.

      To find the service container name for your subscription, in Visual Studio double click your service reference namespace in Solution Explorer. This opens Object Explorer. Select and expand your service reference namespace to reveal the series types and service container type for your subscription.


      For the InfoUSA service you are using for this project the container type name is InfoUSAHistoricalBusinessContainer, circled in red in the following screenshot.

      Object Explorer with Namespace Expanded
      
      Class GetBusinessData
          Private context As InfoUSAHistoricalBusinessesContainer
          Private serviceUri As Uri
      End Class
      
      
  3. Create a constructor for your GetBusinessData class.

    The constructor initializes the class’s private variables and creates credentials for the user.

    The serviceUri is the https link to your service which you copied to your clipboard in Step 2.2.c above. The context is the container for this service. It derives from DataServiceContext in the System.Data.Services.Client namespace and contains, among other things, your credentials.

    
    Public Sub New()
        serviceUri = New Uri(SERVICE_URI) ' SERVICE_URI is the URL you copied to your clipboard in Step 2.2
        context = New InfoUSAHistoricalBusinessesContainer(serviceUri) 
        context.Credentials = New NetworkCredential(UNIQUE_USER_ID, ' Your Live Id
                                                    SECURE_PWD)     ' Your “Dallas” Account Key
    End Sub
    
    
  4. Create a public method within your GetBusinessData class that returns a generic list. For our program the generic type is Nixie, though it could be any of the data series from this service (inside blue rectangles in the previous screenshot (Historical_Business, NewBusiness, or Nixie).

    This method queries the Nixie series. If the query is successful the resulting generic list is returned. If the query is unsuccessful for any reason an error message is displayed and null is returned.

    
    Public Function getData() As IList(Of Nixie)
        Dim query As IEnumerable(Of Nixie)
    
        query = From c In context.Nixie
                Select c
    
        Try
            Return query.ToList
        Catch e As Exception
            Console.WriteLine("ERROR: {0} ", e.Message)
            Return Nothing
        End Try
    End Function
    
    
    The query can be any LINQ query and may optionally include the where filter and/or orderby. For more information on LINQ queries see LINQ Query Expressions (C# Programming Guide).

    The following query filters for CompanyName and State, then sorts the results in ascending order by ZipCode.

    
    query = From c In context.Nixie
            Where c.CompanyName <> "" And c.State = "DE" ' no empty company names and from Delaware only
            Order By (c.ZipCode), (c.CompanyName)
            Select c
    
    
  5. Write the code in Main() that will utilize your GetBusinessData class to obtain the data and then display the results.

        
    Sub Main()
        Dim dataList As IList(Of Nixie)
        Dim busData As GetBusinessData = New GetBusinessData()
        dataList = busData.getData()
    
        If Not dataList Is Nothing Then
            Console.WriteLine("{0,-20} {1,10} {2,-35} {3,10}", "City",
                                                               "Zip Code",
                                                               "Business Name",
                                                               "Phone")
            Console.WriteLine("{0,-20} {1,10} {2,-35} {3,10}", "--------------------",
                                                               "----- ----",
                                                               "-----------------------------------",
                                                               "----------")
    
            Dim d As Nixie
            For Each d In dataList
                Console.WriteLine("{0,-20} {1,5}{2,5} {3,-35} {4,10}", d.City,
                                                                       d.ZipCode().ToString().PadLeft(5, "0"c),
                                                                       GetZip4(d.Zip4),
                                                                       d.CompanyName,
                                                                       d.Phone)
            Next
    
        End If
        Console.Write("Tap any key to exit program. ")
        Console.ReadKey()
    End Sub
    
    
    
    In Visual Basic there is no equivalent to the C# expression booleaExpression ? returnValueIfTrue : returnValueIfFalse so you need to create the following function to handle the Zip4 field neatly.

    
    Function GetZip4(ByVal Zip4) As String
        If Zip4 Is Nothing Then
            GetZip4 = "     " ' if no Zip+4 return 5 spaces
        Else
            GetZip4 = "-" + Zip4.ToString.PadLeft(4, "0"c) ' return "-" plus Zip+4 padded left with "0" for values < 1000
        End If
    End Function
    
    

The Completed Program

The following C# code is the completed program.


Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Net                            ' needed for authentication
Imports InfoUSABusinessData.InfoUSABusinesses ' RESTful proxy to data

Module Module1
    Sub Main()
        Dim dataList As IList(Of Nixie)
        Dim busData As GetBusinessData = New GetBusinessData()
        dataList = busData.getData()

        If Not dataList Is Nothing Then
            Console.WriteLine("{0,-20} {1,10} {2,-35} {3,10}", "City",
                                                               "Zip Code",
                                                               "Business Name",
                                                               "Phone")
            Console.WriteLine("{0,-20} {1,10} {2,-35} {3,10}", "--------------------",
                                                               "----- ----",
                                                               "-----------------------------------",
                                                               "----------")

            Dim d As Nixie
            For Each d In dataList
                Console.WriteLine("{0,-20} {1,5}{2,5} {3,-35} {4,10}", d.City,
                                                                       d.ZipCode().ToString().PadLeft(5, "0"c),
                                                                       GetZip4(d.Zip4),
                                                                       d.CompanyName,
                                                                       d.Phone)
            Next

        End If
        Console.Write("Tap any key to exit program. ")
        Console.ReadKey()
    End Sub

    Function GetZip4(ByVal Zip4) As String
        If Zip4 Is Nothing Then
            GetZip4 = "     " ' if no Zip+4 return 5 spaces
        Else
            GetZip4 = "-" + Zip4.ToString.PadLeft(4, "0"c) ' return "-" plus Zip+4 padded left with "0" for values < 1000
        End If
    End Function
End Module

'-------------------------------------------------
Class GetBusinessData
    '  These constants should be used for this demo only
    '  In a production environment you would write code for the user to input their id values OR
    '    to retrieve it from a database.
    '  The account key should be encrypted to keep it secure. Do not pass the encrypted key to Dallas.
    '     USER_ID is your Live Id, and
    '     SECURE_ACCOUNT_KEY is your account key (found at the Marketplace under the Account keys tab)
    Private Const SERVICE_URI = "<URL you pasted to your clipboard in Step 2.2>"
    Private Const UNIQUE_USER_ID = <your Live Id>
    Private Const SECURE_PWD = <your Dallas AccessKey>

    Private context As InfoUSAHistoricalBusinessesContainer
    Private serviceUri As Uri

    Public Sub New()
        serviceUri = New Uri(SERVICE_URI)
        context = New InfoUSAHistoricalBusinessesContainer(serviceUri)
        context.Credentials = New NetworkCredential(UNIQUE_USER_ID, SECURE_PWD)
    End Sub

    Public Function getData() As IList(Of Nixie)
        Dim query As IEnumerable(Of Nixie)

        query = From c In context.Nixie
                Where c.CompanyName <> "" And c.State = "DE"   ' no empty company names and from Delaware only
                Order By (c.ZipCode), (c.CompanyName)
                Select c

        Try
            Return query.ToList
        Catch e As Exception
            Console.WriteLine("ERROR: {0} ", e.Message)
            Return Nothing
        End Try
    End Function
End Class

Had this been an ASP.NET web page instead of a Console Application, the results could have easily been bound to a DataGrid using the following code in place of the foreach loop above:

myDataGridView.DataSource = dataList;
Show: