CRUD operations with OData

In this recipe we will discuss how to implement create, update, and delete operations, also known as CRUD operations using DataServiceCollection and Context class. Here are the mappings for HTTP Verb to OData operation:

HTTP

OData

GET

Read

POST

Update

PUT

Insert

DELETE

Delete

Getting ready

For this sample, we will be using the editable OData API exposed by odata.org. Just a note, at the time of writing the book this service was provided for testing OData edit features with some restrictions.

You can browse OData using http://services.odata.org/(S(bltvbobia1rthiavqczdcr1u))/OData/OData.svc/. We will be using this link to consume the data in this recipe. For simplicity, we shall only update the categories.

How to do it...

To consume sample editable OData, we first need to generate the proxy class using the DataSvcUtil using the following command-line:

datasvcutil /uri:http://services.odata.org/(S(bltvbobia1rthiavqczdcr1u))/OData/OData.svc/ /out:.EditODataModel.cs /Version:2.0 /DataServiceCollection

How to do it...
  1. Right-click on the solution folder Ch4_Recipes and add a new Phone Project with a name Recipe4_ODataCRUD.
  2. Now add the proxy class EditODataModel.cs we generated into the project by right-clicking and selecting Add Existing Item. You can also use Windows Explorer to just copy and paste the file into the project.
  3. Add a reference to the assembly System.Data.Services.Client that comes with the SDK to the project.
  4. Open the MainPage.xaml file and let's add a ListBox control with two text blocks, one for Category ID and another for Category Name. Add the Binding property to both of them. Also, add the SelectionChanged event for the ListBox. Right-click on OnSelect and click on Navigate to Event Handler to create the empty OnSelect event method:
    <Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
    <TextBlock x:Name="ApplicationTitle" Text="Ch4 Recipes" Style="{StaticResource PhoneTextNormalStyle}"/>
    <TextBlock x:Name="PageTitle" Text="OData CRUD" Margin="9,- 7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>
    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <ListBox x:Name ="lstResults" Grid.Row="3" Grid.Column ="1" ItemsSource="{Binding}" SelectionChanged="OnSelect">
    <ListBox.ItemTemplate>
    <DataTemplate>
    <Grid>
    <Grid.RowDefinitions>
    <RowDefinition Height="*" />
    <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="20"/>
    <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding ID}" FontWeight="Bold" Foreground="OrangeRed"/>
    <TextBlock Grid.Row="0" Grid.Column="1" TextWrapping="Wrap" Text="{Binding Name}" FontWeight="Bold" FontStretch="Expanded" Foreground="OrangeRed"/>
    </Grid>
    </DataTemplate>
    </ListBox.ItemTemplate>
    </ListBox>
    </Grid>
    </Grid>
    
  5. Windows Phone 7.1 SDK comes with most commonly used icons. Create a new folder in the project and name it Images. Now right-click on the Images folder and select Add Existing Items. Navigate to your local drive Program FilesMicrosoft SDKs as shown in the following screenshot and select appbar.new.rest.png.
    How to do it...
  6. After the grid, add the ApplicationBar at the bottom to display one icon to add a new Category. Also, add the click event to map to the ButtonAdd_Click method:
    <phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar BackgroundColor="Orange" IsVisible="True" IsMenuEnabled="True">
    <shell:ApplicationBarIconButton IconUri="/Images/appbar.new.rest.png" Click="ButtonAdd_Click" Text="Add Task"/>
    </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>
    
  7. Open the MainPage.xaml.cs file and include the following using declarations at the beginning of the page:
    using ODataDemo;
    using System.Data.Services.Client;
    using System.Windows.Controls.Primitives;
    
  8. Let's add the following variables just before the MainPage constructor:
    private Uri svcUri;
    private ODataDemo.DemoService ctx;
    private DataServiceCollection<ODataDemo.Category> rslts;
    
  9. Next, add the following code to the MainPage method. Here we are creating the instance of the Uri and calling the DemoService. Similar to the last recipe, we will save the Category collections in the DataServiceCollection and call LoadAsync:
    public MainPage_Loaded(object sender, RoutedEventArgs e)
    {
    svcUri = new Uri(@"http://services.odata.org/ (S(bltvbobia1rthiavqczdcr1u))/OData/OData.svc/");
    var query = "Categories";
    // create context
    ctx = new ODataDemo.DemoService(svcUri);
    rslts = new DataServiceCollection<ODataDemo.Category>(ctx);
    rslts.LoadCompleted += new EventHandler <LoadCompletedEventArgs>(rslts_LoadCompleted);
    rslts.LoadAsync(new Uri(query, UriKind.Relative));
    }
    
  10. Let's add the method rslts_LoadCompleted. Here we check for any errors, otherwise we assign the query results to the DataContext:
    private void rslts_LoadCompleted(object sender, LoadCompletedEventArgs e)
    {
    if (e.Error == null)
    {
    this.DataContext = rslts;
    }
    else
    {
    MessageBox.Show(string.Format("Error: {0}", e.Error.Message));
    }
    }
    
  11. Now let's add the code in the OnSelect event method. Here we get the SelectedIndex and pass it as a query string. This is used for selecting:
    private void OnSelect(object sender, SelectionChangedEventArgs e)
    {
    var selector = (Selector)sender;
    if (selector.SelectedIndex == -1)
    return;
    this.NavigationService.Navigate(new Uri("/CategoryForm.xaml?selIndex = " + selector.SelectedIndex, UriKind.Relative));
    selector.SelectedIndex = -1;
    }
    
  12. Next, we added the toolbar at the bottom for adding new items. Let's add the method to navigate to CategoryForm.xaml with query string selIndex as zero. The reason for zero is to indicate that it is a new category:
    private void ButtonAdd_Click(object sender, EventArgs e)
    {
    this.NavigationService.Navigate(new Uri("/CategoryForm.xaml?selIndex = 0", UriKind.Relative));
    }
    
  13. Now let's add a new page called CategoryForm.xaml to the project. As this is for updating the Category collection, let's add two textboxes and a save button, which would look like the following code snippet:
    <Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
    <TextBlock x:Name="ApplicationTitle" Text="Edit OData App" Style="{StaticResource PhoneTextNormalStyle}"/>
    <TextBlock x:Name="PageTitle" Text="Category" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>
    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="28,43,0,0" Name="textBlock1" Text="ID" VerticalAlignment="Top" Width="115" />
    <TextBox Height="72" HorizontalAlignment="Left" Margin="12,68,0,0" Name="txtID" Text="" VerticalAlignment="Top" Width="438" />
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="28,146,0,0" Name="textBlock2" Text="Name" VerticalAlignment="Top" Width="115" />
    <TextBox Height="72" HorizontalAlignment="Left" Margin="12,171,0,0" Name="txtName" Text="" VerticalAlignment="Top" Width="438" />
    <Button Content="Save" Height="72" HorizontalAlignment="Left" Margin="12,249,0,0" Name="button2" VerticalAlignment="Top" Width="136" />
    </Grid>
    </Grid>
    
  14. Now, open the CategoryForm.xaml.cs file and add a using declaration at the top of the page for ODataDemo:
    using ODataDemo;
    
  15. Next, we need to hold the new form data and when the Save button is clicked it should be accessed in the MainPage so it is added to the DataServiceCollection. We can achieve this by either serializing the object to local storage, or just holding a global static variable. Open the App.xaml.cs file and add static variable _category:
    public static ODataDemo.Category _category;
    
  16. When the user clicks the Save button, we save the ID and Name to the global variable and then navigate back to the previous page:
    private void btnSave_Click(object sender, RoutedEventArgs e)
    {
    App._category = new Category();
    if (txtID.Text != "")
    App._category.ID = int.Parse(txtID.Text);
    if (txtName.Text != "")
    App._category.Name = txtName.Text;
    NavigationService.GoBack();
    }
    
  17. Now open the MainPage.xaml.cs file and add the OnNavigatedTo method. In this method, we check if there is anything in the static variable and then add the category object to the collection.
    // called when the current frame becomes active
    protected override void OnNavigatedTo(System.Windows.Navigation. NavigationEventArgs e)
    {
    if (App._category != null)
    {
    rslts.Add(App._category);
    }
    base.OnNavigatedTo(e);
    }
    
  18. Let's go back to CategoryForm.xaml.cs and add the OnNavigatedTo method here too. Before the method, declare the string variable selIndex. We will get the query string selIndex using the NavigationContext class. We will use this variable in the page-loaded event method to get the collection item.
    private string selIndex;
    protected override void OnNavigatedTo (System.Windows.Navigation.NavigationEventArgs e)
    {
    base.OnNavigatedTo(e);
    if (!NavigationContext.QueryString.TryGetValue("selIndex", out selIndex))
    {
    MessageBox.Show("Error");
    }
    }
    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
    {
    if (int.Parse(selIndex) != 0)
    {
    txtID.Text = App._category.ID.ToString();
    txtName.Text = App._category.Name.ToString();
    }
    }
    
  19. Now, press F5 and run. You should see the list of categories and when you select the category name you will be navigated to CategoryForm to edit and save. You can also click on the + button in the navigation bar to save a new category.
    How to do it...

How it works...

First, we displayed the list of categories available in the OData list. By getting the list using DataServiceCollection and context classes, we are making use of the automatic tracking for changes to the list.

By updating the object it is marked as changed. OData automatically updates the OData data source. We can add to and update the collection using DataServiceCollection's add and update methods. Just like adding to and updating the collection, we can also remove from the collection.

There's more...

You can easily navigate the structure of OData using free tools available online.

OData Explorer

There are many different explorers available online for browsing the OData:

  1. OData Explorer by Microsoft:

    http://www.silverlight.net/content/samples/odataexplorer/default.html

  2. SESAME Data Browser also supports OData. At the time of writing this book, this was still a BETA:

    http://metasapiens.com/sesame/data-browser/preview/

  3. LINQPad is another choice that supports OData:

    http://www.linqpad.net/

See also

Check Chapter 6 for REST web services and Chapter 7 for WCF web services.

Also, check the following online resources for further understanding of OData:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset