Introduction

I have been working on a hybrid mobile application that requires displaying/containing a few mobile apps in a WebView control. In the background, some HTTP requests need to go through to collect data and do further processing. We need to maintain the same session in all of the web requests going through the mobile app. This means all web (HTTP) requests originated by the Webview as well as our background (HttpClient) requests need to share cookies, cache, etc. So how can we achieve this?

System.Net.Http.HttpClient

HttpClient has become the go-to class for all things HTTP, especially with the support of HttpClient in PCLs (Portable Class Library), who can resist it? So my first thought when I considered this requirement was to use HttpClient with a HttpClientHandler, preserve the session cookies, and share them with the WebView. I started my initial research, and I found that somebody has done exactly that, you can find it here. This gave me some more confidence for a successful solution.

This first approach would mean using HttpClient (along with a HttpClientHandler) to hold cookies and share them with the WebView. However, this would be error-prone because I will need to continuously monitor both cookies and update the other group of requests. Plus, sharing the data cache between the WebView and HttpClient would still be an issue that I was not sure how to address.

Windows.Web.HttpClient

Before going further, I thought I would look for an alternative, and I found Windows.Web.HttpClient. This one seemed very similar to System.Net.Http.HttpClient, but the implementation is quite different, regardless of the exact matching of the name :). I found this video (below) from Microsoft’s //Build conference that refers to this different implementation of HttpClient for Windows specific development.

Five Great Reasons to Use the New HttpClient API to Connect to Web Services

Five Great Reasons to Use the New HttpClient API to Connect to Web Services

Apparently the Windows implementation of HttpClient gives you the ability customise all aspects your HTTP requests. The video above lists the following five reasons why you should use Windows.Web.HttpClient:

  1. Shared Cookies, Cache, and Credentials
  2. Strongly Typed headers => fewer bugs
  3. Access to Cookies and Shared Cookies
  4. Control over Cache and Shared Cache
  5. Inject your code modules into the processing pipe-line => cleaner integration.

When I read the first statement above, I really thought that this is too good to be true :), just exactly what I am looking for. So I decided to give it a go. As you can see some of the features listed for this HttpClient (Windows implementation) are similar to what we have in the System.Net world, but this gives us extra capabilities.

HttpClientHandlers vs HttpBaseProtocolFilter

It is worth mentioning that Windows.Web library does not have HttpClientHandlers that we are familiar with in System.Net, instead it gives you the ability do more with HttpBaseProtocolFilter, and this is a key point. HttpBaseProtocolFilter enables developers to customise/manipulate HTTP requests (headers, cookies, cache, etc) and the changes will be applied across the board in your application. This applies whether you are making a HTTP request programmatically using HttpClient or via the user interface (using a WebView for instance).

Code Time

[code lang=”csharp”]
// creating the filter
var myFilter = new HttpBaseProtocolFilter();
myFilter.AllowAutoRedirect = true;
myFilter.CacheControl.ReadBehavior = HttpCacheReadBehavior.Default;
myFilter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.Default;

// get a reference to the cookieManager (this applies to all requests)
var cookieManager = myFilter.CookieManager;

// make the httpRequest
using (var client = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "your-url-address");

// add any request-specific headers here
// more code been omitted

var result = await client.SendRequestAsync(request);
result.EnsureSuccessStatusCode();

var content = await result.Content.ReadAsStringAsync();

// now we can do whatever we need with the html content we got here 🙂
// Debug.WriteLine(content);
}

// assuming that the previous request created a session (set cookies, cached some data, etc)
// subsequent requests in the webview will share this data
myWebView.Navigate(new Uri("your-url-address"));

[/code]

Hopefully this short code snippet gives you a good idea of what you can do with Windows Implementation of HttpClient. Notice that myWebView automatically shares the CookieManager implicitly.

Other Apps?

One might ask about how will this impact other apps? It doesn’t. The Windows.Web library was designed to work across all requests in one app. Therefore, you do not need to be concerned about impacting other apps or leaking your data to other external requests.

Conclusions

Someone wise once said “with great power, comes great responsibility”. This should be remembered when using HttpBaseProtocolFilter with your HTTP requests as it can (as mentioned above) impact all your subsequent requests. Hope you find this useful and I would love to hear your comments and feedback.

References:

  • https://channel9.msdn.com/Events/Build/2013/4-092
  • https://social.msdn.microsoft.com/Forums/windowsapps/en-US/6aa75d2f-05bd-4e8d-a435-0aa3407b73e6/set-cookies-to-webview-control?forum=winappswithcsharp
  • http://blog.rajenki.com/2015/01/winrt-shared-cookies-between-webview-and-httpclient/
  • http://blogs.msdn.com/b/wsdevsol/archive/2012/10/18/nine-things-you-need-to-know-about-webview.aspx#AN7
Category:
Application Development and Integration, Mobile, Security, Technology, WebAPI
Tags:
, , , ,

Join the conversation! 1 Comment

  1. Thank for this post! I want to load an iframe into my webview. I have a constant html string, and I replace the iframe’s src to a link i get from an api. My problem is that the iframe doesn’t load if I set the src with relative url, but with absolute url it also won’t load due to security reasons. I try to set a referer url, but that also doesn’t help. Is there something like Android’s loadDataWithBaseUrl in Windows Phone? That would do the trick.

Comments are closed.