Creating an OData Wrapper

,

The previous section looked at querying an OData service using the OData model class. Although accessing the OData service model classes directly from a viewmodel is possible, it can make unit testing difficult because it relies on the actual OData producer.

In the sample for this chapter, an intermediary class called EbayClient performs all OData queries. EbayClient implements the custom IEbayClient interface, shown in the following excerpt:

public interface IEbayClient
{
    void SearchItemsAsync(string query,
                          int beginIndex = 0, int maxItems = 0);
    event EventHandler<SearchItemsCompleteEventArgs> SearchItemsComplete;
}

By using the IEbayClient interface and not a concrete implementation, we are able to substitute the EbayClient implementation for a mock type to enable testing of the user interface without needing to send data over the wire.

The IEbayClient interface is designed to be used asynchronously; the SearchItemsAsync method has a void return type, and an event is used to signal that the call has completed. When the search completes, the SearchItemsComplete method is raised using a custom extension method (see Listing 27.2).

The static HttpUtility.UrlEncode method transforms any special characters entered by the user into URL compatible characters. This prevents the user from injecting OData query options, or inadvertently causing the request to fail.

LISTING 27.2. EbayClient Class


public class EbayClient : IEbayClient
{
    DataServiceCollection<Item> searchResult;

    public void SearchItemsAsync(string query,
                                 int beginIndex = 0, int maxItems = 0)
    {
        EBayData ebayData
                  = new EBayData(new Uri("http://ebayodata.cloudapp.net/"));

        searchResult = new DataServiceCollection<Item>(ebayData);

        searchResult.LoadCompleted
            += (sender, args) =>
                {
                    if (args.Error != null)
                    {
                        SearchItemsComplete.Raise(this,
                            new SearchItemsCompleteEventArgs(
                                    null, query, args.Error));
                        return;
                    }
                    SearchItemsComplete.Raise(this,
                        new SearchItemsCompleteEventArgs(searchResult, query));
                };
        string parameter = HttpUtility.UrlEncode(query);

        IQueryable<Item> serviceQuery
            = ebayData.Items.AddQueryOption("search", parameter)
                            .AddQueryOption("$skip", beginIndex)
                            .AddQueryOption("$top", maxItems);

        //serviceQuery = from item in serviceQuery
        //                where item.CurrentPrice > 100.0
        //                select item;

        searchResult.LoadAsync(serviceQuery);
    }

    public event EventHandler<SearchItemsCompleteEventArgs> SearchItemsComplete;
}


The SearchItemsCompleteEventArgs class extends the custom ResultEventArgs, which contains the result produced by the OData proxy, the type of which is defined by a generic parameter. An optional parameter allows it to supply an Exception instance if the call fails (see Listing 27.3).

LISTING 27.3. ResultEventArgs Class


public class ResultEventArgs<T> : EventArgs
{
    public T Result { get; private set; }
    public Exception Error { get; private set; }

    public ResultEventArgs(T result, Exception error = null)
    {
        Result = result;
        Error = error;
    }
}


The SearchItemsCompleteEventArgs adds a string Query property, which identifies the original query (see Listing 27.4).

LISTING 27.4. SearchItemsCompleteEventArgs Class


public class SearchItemsCompleteEventArgs
    : ResultEventArgs<ObservableCollection<Item>>
{
    public string Query { get; private set; }
    public SearchItemsCompleteEventArgs(
        ObservableCollection<Item> result, string query, Exception error = null)
        : base(result, error)
    {
        Query = query;
    }
}


The sample also comprises a view named EbaySearchView and its viewmodel: EbaySearchViewModel.

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

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