Archives For Windows Phone

While I was reinstalling my laptop this week, I ran into some friction getting my Brick Manager development environment going again. My issue turned out to be pretty simple, and I thought I would share out how to solve the issue to help out others that follow on behind me(because I couldn’t find anything on the interwebz).

After syncing my solution down to my newly configured dev machine, there was a System.IO.FileNotFoundException thrown by the  public static Result Open(string, out Sqlite3DatabaseHandle, int, IntPtr) method within the SQLite.cs; in particular, the exception was thrown by the Sqlite3.sqlite3_open_v2() call.

SQLite exc blog post - 01

Exception details:

  • Type: System.IO.FileNotFoundException
  • Message: The specified module could not be found.
  • HRESULT: 0x8007007E

 

SQLite exc blog post - 03At the root of the exception was a missing SQLite extension for Visual Studio. I had the SQLite-net and SQLite-net-wp8 NuGet packages, but Visual Studio didn’t automatically link into the SQLite for Windows Phone extension (even though it was installed).

To re-add this to your VS solution, do the following steps:

  1. Open up the project’s references by secondary-clicking on the ‘References’ node in the solution explorer and selecting ‘Add Reference…’
  2. In the Reference Manager, select ‘Windows Phone SDK 8.0’
  3. Select ‘Extensions’
  4. Check the box for ‘SQLite for Windows Phone’ if it isn’t already selected. If it isn’t in the list, then you will need to install the extension (but I will assume you already know how to do that Smile)

SQLite exc blog post - 02

Once I selected the box, everything was once again copasetic and all was good in the universe once more.

Hope this helps!
Cliff

This blog post starts to cover a number of interesting Windows platform development challenges that I ran into as I built out my Brick Manager app. While the code was initially written for Windows Phone, it also applies to building Windows Store apps. Given that I started the app out as a learning experiment a bit over a year ago, it’s funny that it’s taken me a year to get the first one of these out. Feel free to share your feedback below. – CRS

At the heart of my Brick Manager app is communication with the BrickSet web services. As I started using the service, I wanted to take advantage of HttpClient and the async keyword, but I ran into two challenges up front: (1) Huw uses ASMX for his web service (good luck finding a blog or StackOverflow article discussing how to wire up against one of those) and (2) the site only returns XML (while most Windows/HttpClient blogs only talk about wiring up JSON).

The logic of the XML communications eventually settled on the following pattern:

  1. Instantiate HttpClient to use for the web service communication
  2. Instantiate a CancellationToken to allow me to set a time-out
  3. Parse the result into an XElement data structure, and pass that back to the caller
  4. From the caller, pass the returned XElement into the appropriate parser

I eventually compartmentalized my service calls into a static class, which centralized all of the web service call logic into one place (which not only deduped the code, but also improved stability and perf).

For the web service communication (steps 1-3 above), this is a cleaned up version of my GetBrickSetData method:

private static async Task<XElement> GetBrickSetData(string url) {
  using (HttpClient _client = new HttpClient()) {
    using (var _cts = new CancellationTokenSource(TIMEOUT_DEFAULT)) {
      try {
        var _result = await _client.GetAsync(url, _cts.Token);
        var _data = XElement.Parse(await _result.Content.ReadAsStringAsync());
        return _data;
      } catch (OperationCanceledException _e) {
        // Code to handle timed out exception
      } catch (System.Net.Http.HttpRequestException _e) {
        if (_e.Message.ToLower().Contains("Response status code") && _e.Message.ToLower().Contains("404")) {
          // Code to handle timed out exception
        }
      }
    }
    return null;
  }
}

One item that is worth calling out is the CancellationToken. I mentioned this as step 2 above, but this was a later addition to my code logic, which I added when BrickSet was undergoing a DoS attack. During that time, the app experience looked to users like it was in a perpetual unresponsive state. Adding the CancellationToken enables me to take the default 60 second timeout to something closer to 3 seconds, but the addition did require me to tease apart the typical HttpClient.GetStringAsync() call you see in code samples everywhere into the two calls above.

Once I get the data back from the above, I then have to parse apart the huge clump of XML For me, I found it easiest to use LINQ to XML to parse the data apart. In the code below, which is pulled from my method that parses the BrickSet set themes, I grab the namespace from the XML and then iterate through each elements in the “themes” node.

public static async Task<IEnumerable<Theme>> GetThemes() {
  string _url = String.Format(BRICKSET_ASMX + "/getThemes?apiKey={0}", BRICKSET_API_KEY);

  XElement _themeData = await GetBrickSetData(_url);

  //parse the results
  XNamespace _ns = _themeData.Attribute("xmlns").Value;
  var _themes = (from themes in _themeData.Elements(_ns + "themes")
                 select new Theme {
                 ThemeName = (string)themes.Element(_ns + "theme").Value,
                 Sets = int.Parse(themes.Element(_ns + "setCount").Value)
                 });
  return _themes;
}

In the end, [I believe that] I landed on a pretty elegant solution, but it can be a real pain to get it right. Not only do you need to really know the XML structure coming off the server, but you need to be able to handle the parsing in a bullet-proof fashion – one parsing error and the code goes bananas.

Parsing errors to keep your eye out for:

  • XML elements that need more robust parsing (e.g., turning 0 | 1 into a Boolean)
  • XML elements that are occasionally null
  • XML elements that are child nodes (and aren’t always present)
  • Optional XML elements that may or may not be there (e.g., when you’re not passing a user ID)

My code (above) gives some decent starting pointers for basic XML parsing, and I’ll dig into my travels through LINQ-to-XML-land in a future blog post.

I hope this helps!
Cliff