Home > Articles > Mobile Application Development & Programming

  • Print
  • + Share This
From the author of Connecting to the Service

Connecting to the Service

The code that you have to write to interact with the OData service is the same as in Part 3, when talking about Windows Phone 7.5. This is because the OData client library offers the same implementation and can be used the same way for both versions. There are basically two differences: 1) as I said previously, the Windows Phone 8 emulator cannot access local resources directly, so you have to specify the IP address for the server rather than the service name; and 2) the code that creates an instance of the proxy class for the service is placed inside the OnNavigatedTo event handler. Otherwise, the code is the same as that used for Windows Phone 7.5 and for Windows 8 Store Apps in Part 4.

Listing 3 shows the code that's responsible for establishing a connection to the service-passing credentials, as well as for keeping in memory the information retrieved from the service.

Listing 3—Connecting to the OData service and declaring class-level variables.

'The following directives are required
'Imports System.Data.Services.Client
'Imports MobileOrdersClient.OrdersServiceReference

'Store the service URL. Replace localhost with your server's name
Private Shared ReadOnly ServiceUri As New _
        Uri("http://192.168.1.3/ExposingOData/ApplicationData.svc")

'Two collections for storing the list of entities exposed by the service
Private Property orders As DataServiceCollection(Of Order)
Private customers As DataServiceCollection(Of Customer)

'Represent the LightSwitch's intrinsic data
Private applicationData As OrdersServiceReference.ApplicationData

'Constructor
Public Sub New()
InitializeComponent()
SupportedOrientations = SupportedPageOrientation.Portrait Or SupportedPageOrientation.Landscape

End Sub

Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs)
    'Start an instance of the WCF service
    If Me.applicationData Is Nothing Then
        Me.applicationData = New OrdersServiceReference.ApplicationData(ServiceUri)
    End If

    'Pass credentials of a LightSwitch user
    Me.applicationData.Credentials = New NetworkCredential("TestUser", "TestUser$")

    'Create instances of collections to store data
    Me.orders = New DataServiceCollection(Of Order)(applicationData)
    Me.customers = New DataServiceCollection(Of Customer)(applicationData)

    'Declare event handlers for handling loaded data
    AddHandler Me.orders.LoadCompleted, AddressOf orders_LoadCompleted
    AddHandler Me.customers.LoadCompleted, AddressOf customers_LoadCompleted

    'Load customers and orders
    loadCustomers()
    loadOrders()
End Sub

As a reminder, the DataServiceCollection(Of T) class allows for storing collections of objects exposed by a WCF data service. This class inherits from ObservableCollection(Of T), which means that it implements the necessary infrastructure to send and receive notifications of changes over the items it contains. When the page is opened, a check is made to ensure that an instance of the service isn't already alive. The code accomplishes this with the first If block in the event handler. This is important if your app has more than one page and the page that interacts with the service can be opened at any time by the user, and it avoids generating a second instance if one already exists.

The next step is writing code that loads data. The code in Listing 4 is the same code we used for Windows Phone 7.5 in Part 4 of this series.

Listing 4—Loading data asynchronously.

'Querying the data service for the full list of items
'and loading data asynchronously
Private Sub loadCustomers()
    Dim query = From cust In Me.applicationData.Customers
                Order By cust.CompanyName Descending
                Select cust

    customers.LoadAsync(query)

End Sub

Private Sub loadOrders()
    orders.LoadAsync(New Uri("http://192.168.1.3/exposingodata/ApplicationData.svc/Orders",
           UriKind.Absolute))
End Sub

Private Sub orders_LoadCompleted(sender As Object, e As LoadCompletedEventArgs)
    'If the feed exposes paged data, load the next chunk of data
    If e.Error Is Nothing Then
        If Me.orders.Continuation IsNot Nothing Then
            Me.orders.LoadNextPartialSetAsync()
        Else
            'Otherwise simply assign the data collection as the
            'data source of the ContentPanel grid
            Me.ContentPanel.DataContext = Me.orders
        End If
    Else
        MessageBox.Show(e.Error.Message)
    End If

End Sub

Private Sub customers_LoadCompleted(sender As Object, e As LoadCompletedEventArgs)
    If e.Error Is Nothing Then
        'No assignment of the customers collection
        'because it will not be displayed in the UI
        If Me.customers.Continuation IsNot Nothing Then
            Me.customers.LoadNextPartialSetAsync()
        End If
    Else
        MessageBox.Show(e.Error.Message)
    End If
End Sub

The final step is writing code that executes some operations over data, such as adding, removing, and saving orders. Listing 5 demonstrates this code.

Listing 5—Executing data operations.

Private Sub InsertButton_Click(sender As Object, e As EventArgs)
    'Hard coding the creation of a new order
    'Assuming there is already a customer with the specified name
    Dim customerInstance = customers.Where(Function(c) _
        c.CompanyName.ToLower.Contains("del sole")).FirstOrDefault

    Dim newOrder As New OrdersServiceReference.Order
    With newOrder
        .OrderDate = Date.Today
        .Description = "Order of Natural Water"
        .ShippedDate = Date.Today.AddDays(1)
        .RequiredDate = Date.Today.AddDays(2)
        .Customer = customerInstance
    End With

    Me.orders.Add(newOrder)

End Sub

Private Sub DeleteButton_Click(sender As Object, e As EventArgs)
    Dim currentOrder = TryCast(Me.OrdersListBox.SelectedItem, OrdersServiceReference.Order)

    If currentOrder IsNot Nothing Then
        Me.orders.Remove(currentOrder)
    End If

End Sub

Private Sub SaveButton_Click(sender As System.Object, e As System.EventArgs)
    'Start saving asynchronously
    Me.applicationData.BeginSaveChanges(SaveChangesOptions.Batch,
     AddressOf OnChangesSaved, Me.applicationData)
End Sub

Private Sub OnChangesSaved(result As IAsyncResult)
    ''Use the dispatcher to run the operation inside the appropriate thread
    Dispatcher.BeginInvoke(Sub()
                               'Get the instance of the application data
                               Me.applicationData = CType(result.AsyncState, ApplicationData)
                               Try
                                   'Finalize the save operation
                                   Me.applicationData.EndSaveChanges(result)
                                   'Reload data for data-binding
                                   loadOrders()
                               Catch ex As DataServiceRequestException
                                   MessageBox.Show(String.Format("Data service error: {0}",
                                                   ex.Message))
                               Catch ex As Exception
                                   MessageBox.Show(String.Format("Error: {0}", ex.Message))
                               End Try
                           End Sub)

End Sub

The code simulates an insert operation by hard-coding a new instance of an order, rather than providing the user with the ability to specify one. This is intended to make the example simpler, but of course in real-world applications you would provide a specific page with textboxes and other controls.

  • + Share This
  • 🔖 Save To Your Account