Tuesday, September 18, 2012

Windows Store Apps – using a generic service layer

Another perhaps helpful tip when building Windows Store Apps that are connected in some way to the internet: You can easily create a reusable “service layer” for your web requests that make consuming async http urls more of a walk in the park.

With that said, say hello to the GenericServiceLayer for Windows Store Apps.

the idea is simple: extract away as much as possible from the (often) repetitive task of sending web requests in a windows store app.

Usage:

  1. Reference the dll/project
  2. In your viewmodel/datasource/whatever, create a GenericServiceLayer
  3. use it in your code

Setting up a GenericServiceLayer in your code shouldn’t take much more than this:

    public class GenericServiceLayerSample
    {
        private GenericServiceLayer service = null;

        public GenericServiceLayerSample()
        {
            CookieContainer cookieContainer = new CookieContainer();
            HttpMessageHandler handler = new HttpClientHandler() { CookieContainer = cookieContainer, UseCookies = true};
            handler = new InspectorHandler(handler);
            var client = new HttpClient(handler) { BaseAddress = new System.Uri("http://dev.virtualearth.net/REST/v1/Locations/") };

            service = new GenericServiceLayer(client);
        }
    }

Note that the code above also uses the InspectorHandler I wrote about in the previous post.

Now, to use it. It’s really as simple as:

        public async void Sample()
        {
            // get a string response
            var response = await service.GetAsync("Eiffel%20Tower?o=json&key=BingMapsKey");
            // get a Json.NET mapped model
            var responseModel = await service.GetAsync<MyEiffelTowerModel>("Eiffel%20Tower?o=json&key=BingMapsKey");
        }

Passing in parameters/content is done in a structured way using the normal syntax, for example:

            // pass in content via PUT and get a string response
            HttpContent content = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("SomeInnerContent", "innercontent")
            });
            var response = service.PutAsync("Eiffel%20Tower?o=json&key=BingMapsKey", content);

The methods (GET, POST, PUT) exposed in the GenericServiceLayer all implement IAsyncOperationWithProgress<Tresult, int> which easily enables you to also report progress on the requests made:

            // get a string response and listen for progress
            var response = service.GetAsync("Eiffel%20Tower?o=json&key=BingMapsKey");
            int reportedProgress = 0;
            response.Progress = (info, progress) =>
            {
                reportedProgress = progress;
            };

The above “reportedProgress” would probably be a property in your viewmodel (or the approach you’re running with that makes use of NotifyPropertyChanged) so that it’d present a visual progress notification in your app when changed.

Perhaps you’ll find this useful, it has proven valuable in the adventures of Windows Store Apps I’m currently embarking on.

Full source code can be downloaded here.

Windows Store Apps – a simple HttpClient request & response debugger

Here’s the deal: Debugging is a pain. Sometimes a huge pain, other times it’s not that big of a deal. Regardless of the case at hand I often find myself digging into the requests and responses of the HttpClient, so therefore I wrote this little helper.
So, with that said, let me introduce you to InspectorHandler for Windows Store apps.
It’s simple really - InspectorHandler is a MessageProcessingHandler that you can add to your HttpClient definition that outputs the request & response from the HttpClient to the debug output window when you’re in debug configuration.
Usage is really straight forward:
  1. Hook up the handler
  2. Create the HttpClient
  3. You’re set.
Continue using the HttpClient just as you normally would with await, ReadAsStringAsync() and all that.
        private async void btnGo_Click_1(object sender, RoutedEventArgs e)
        {
            // declare http handler
            HttpMessageHandler handler = new HttpClientHandler();
            // append the Inspector handler
            handler = new InspectorHandler(handler);
            // allocate a http client on the above handlers
            var client = new HttpClient(handler) { BaseAddress = new System.Uri("http://dev.virtualearth.net/REST/v1/Locations/") };

            // fire request
            var response = await client.GetAsync("Eiffel%20Tower?o=xml&key=BingMapsKey"); // insert a proper bing maps key here otherwise you'll just get the access denied view..
            // output result
            tbContent.Text = await response.Content.ReadAsStringAsync();
        }
      Below is a screenshot of a example app that once the button is pressed fires a GET request to the http://dev.virtualearth.net/REST/v1/Locations/Eiffel%20Tower?o=xml&key=BingMapsKey url and ouputs the result into a textbox.
image  
And some basic interesting details from the request & response objects are now available in the ouput of the debugger:
image  
There you have it. Simple, fairly effective and perhaps useful. Under the hood the InspectorHandler is far from a work of art, but it does the job quite well for being a simple debug tool. Here’s the complete source code:
    public class InspectorHandler : MessageProcessingHandler
    {
        public InspectorHandler(HttpMessageHandler innerHandler)
            : base(innerHandler)
        {
        }

        protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken)
        {
#if DEBUG
            if (request.Content!=null)
            {
                var content = request.Content.ReadAsStringAsync();
                content.Wait();
                Debug.WriteLine(string.Format("INSPECTOR: {0} REQUEST - {1} - {2}", request.Method, request.RequestUri.ToString(), content.Result));
            }
            else
            {
                Debug.WriteLine(string.Format("INSPECTOR: {0} REQUEST - {1}", request.Method, request.RequestUri.ToString()));
            }
#endif
            return request;
        }

        protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken)
        {
#if DEBUG
            if (response.Content!=null)
            {
                var content = response.Content.ReadAsStringAsync();
                content.Wait();
                Debug.WriteLine(string.Format("INSPECTOR: {0} RESPONSE - {1} - {2}", response.RequestMessage.Method, response.StatusCode, content.Result));
            }
            else
            {
                Debug.WriteLine(string.Format("INSPECTOR: {0} RESPONSE - {1} - {2}", response.RequestMessage.Method, response.StatusCode));
            }
#endif
            return response;
        }
    }
If you want it, you can grab it here as a zip containing the class library project ready to be compiled & referenced.