{"id":150,"date":"2014-07-06T10:40:00","date_gmt":"2014-07-06T17:40:00","guid":{"rendered":"https:\/\/simpkins.social\/cliff\/?p=150"},"modified":"2025-03-04T10:45:13","modified_gmt":"2025-03-04T18:45:13","slug":"wpdev-talking-to-xml-web-services","status":"publish","type":"post","link":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/","title":{"rendered":"WPDev: Talking to XML web services"},"content":{"rendered":"\n<p><em>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.&nbsp;Given that I started the app out as a learning experiment a bit over a year ago, it\u2019s funny that it\u2019s taken me a year to get the first one of these out. Feel free to share your feedback below. \u2013 CRS<\/em><\/p>\n\n\n\n<p>At the heart of&nbsp;<a href=\"https:\/\/web.archive.org\/web\/20170531000254\/http:\/\/windowsphone.com\/s?appId=f0178f3e-23ce-4365-b415-056c28e60a00\" target=\"_blank\" rel=\"noreferrer noopener\">my Brick Manager app<\/a>&nbsp;is communication with the&nbsp;<a href=\"https:\/\/web.archive.org\/web\/20170531000254\/http:\/\/brickset.com\/tools\/webservices\" target=\"_blank\" rel=\"noreferrer noopener\">BrickSet web services<\/a>. 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).<\/p>\n\n\n\n<p>The logic of the XML communications eventually settled on the following pattern:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Instantiate\u00a0<a href=\"https:\/\/web.archive.org\/web\/20170531000254\/http:\/\/msdn.microsoft.com\/en-us\/library\/system.net.http.httpclient(v=vs.118).aspx\" target=\"_blank\" rel=\"noreferrer noopener\">HttpClient<\/a>\u00a0to use for the web service communication<\/li>\n\n\n\n<li>Instantiate a CancellationToken to allow me to set a time-out<\/li>\n\n\n\n<li>Parse the result into an XElement data structure, and pass that back to the caller<\/li>\n\n\n\n<li>From the caller, pass the returned XElement into the appropriate parser<\/li>\n<\/ol>\n\n\n\n<p>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).<\/p>\n\n\n\n<p>For the web service communication (steps 1-3 above), this is a cleaned up version of my GetBrickSetData method:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private\u00a0static\u00a0async\u00a0Task&lt;XElement> GetBrickSetData(string\u00a0url) {\n\u00a0\u00a0using\u00a0(&lt;strong>HttpClient _client =\u00a0new\u00a0HttpClient()&lt;\/strong>) {\n\u00a0\u00a0\u00a0\u00a0using\u00a0(var\u00a0&lt;strong>_cts =\u00a0new\u00a0CancellationTokenSource(TIMEOUT_DEFAULT)&lt;\/strong>) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var\u00a0_&lt;strong>result =\u00a0await\u00a0_client.GetAsync(url, _cts.Token);&lt;\/strong>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var\u00a0_data = XElement.Parse(&lt;strong>await\u00a0_result.Content.ReadAsStringAsync()&lt;\/strong>);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0_data;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\u00a0catch\u00a0(OperationCanceledException _e) {\n&lt;span style=\"color: #008040;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Code to handle timed out exception\n&lt;\/span>\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0catch\u00a0(System.Net.Http.HttpRequestException _e) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0(_e.Message.ToLower().Contains(\"Response status code\") &amp;&amp; _e.Message.ToLower().Contains(\"404\")) {\n&lt;span style=\"color: #008040;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Code to handle timed out exception&lt;\/span>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\u00a0\n\u00a0\u00a0\u00a0return\u00a0null;\n\u00a0\u00a0}\n}<\/code><\/pre>\n\n\n\n<p>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&nbsp;<a href=\"https:\/\/web.archive.org\/web\/20170531000254\/http:\/\/msdn.microsoft.com\/en-us\/library\/system.threading.cancellationtoken(v=vs.118).aspx\" target=\"_blank\" rel=\"noreferrer noopener\">CancellationToken<\/a>&nbsp;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&nbsp;<a href=\"https:\/\/web.archive.org\/web\/20170531000254\/http:\/\/msdn.microsoft.com\/en-us\/library\/hh551745(v=vs.118).aspx\" target=\"_blank\" rel=\"noreferrer noopener\">HttpClient.GetStringAsync()<\/a>&nbsp;call you see in code samples everywhere into the two calls above.<\/p>\n\n\n\n<p>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 \u201cthemes\u201d node.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public static async Task&lt;IEnumerable&lt;Theme>> GetThemes() {\n  string _url = String.Format(BRICKSET_ASMX + \"\/getThemes?apiKey={0}\", BRICKSET_API_KEY);\n \n  XElement _themeData = await GetBrickSetData(_url);\n \n  \/\/parse the results\n  &lt;strong>XNamespace _ns = _themeData.Attribute(\"xmlns\").Value;&lt;\/strong>\n  var _themes = (&lt;strong>from themes in _themeData.Elements(_ns + \"themes\")&lt;\/strong>\n                 &lt;strong>select new Theme {&lt;\/strong>\n                 ThemeName = &lt;strong>(string)themes.Element(_ns + \"theme\").Value&lt;\/strong>,\n                 Sets = &lt;strong>int.Parse(themes.Element(_ns + \"setCount\").Value)&lt;\/strong>\n                 });\n  return _themes;\n}<\/code><\/pre>\n\n\n\n<p>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 \u2013 one parsing error and the code goes bananas.<\/p>\n\n\n\n<p>Parsing errors to keep your eye out for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>XML elements that need more robust parsing (e.g., turning 0 | 1 into a Boolean)<\/li>\n\n\n\n<li>XML elements that are occasionally null<\/li>\n\n\n\n<li>XML elements that are child nodes (and aren\u2019t always present)<\/li>\n\n\n\n<li>Optional XML elements that may or may not be there (e.g., when you\u2019re not passing a user ID)<\/li>\n<\/ul>\n\n\n\n<p>My code (above) gives some decent starting pointers for basic XML parsing, and I\u2019ll dig into my travels through LINQ-to-XML-land in a future blog post.<\/p>\n\n\n\n<p>I hope this helps!<br>Cliff<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[8],"tags":[],"class_list":["post-150","post","type-post","status-publish","format-standard","hentry","category-windows-phone"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>WPDev: Talking to XML web services - Cliff Simpkins<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"WPDev: Talking to XML web services - Cliff Simpkins\" \/>\n<meta property=\"og:description\" content=\"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&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/\" \/>\n<meta property=\"og:site_name\" content=\"Cliff Simpkins\" \/>\n<meta property=\"article:published_time\" content=\"2014-07-06T17:40:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-03-04T18:45:13+00:00\" \/>\n<meta name=\"author\" content=\"cliff.simpkins\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"cliff.simpkins\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/blog\\\/2014\\\/07\\\/06\\\/wpdev-talking-to-xml-web-services\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/blog\\\/2014\\\/07\\\/06\\\/wpdev-talking-to-xml-web-services\\\/\"},\"author\":{\"name\":\"cliff.simpkins\",\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/#\\\/schema\\\/person\\\/bba546ac4d77da1fb51bc4030238e864\"},\"headline\":\"WPDev: Talking to XML web services\",\"datePublished\":\"2014-07-06T17:40:00+00:00\",\"dateModified\":\"2025-03-04T18:45:13+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/blog\\\/2014\\\/07\\\/06\\\/wpdev-talking-to-xml-web-services\\\/\"},\"wordCount\":603,\"articleSection\":[\"Windows Phone\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/blog\\\/2014\\\/07\\\/06\\\/wpdev-talking-to-xml-web-services\\\/\",\"url\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/blog\\\/2014\\\/07\\\/06\\\/wpdev-talking-to-xml-web-services\\\/\",\"name\":\"WPDev: Talking to XML web services - Cliff Simpkins\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/#website\"},\"datePublished\":\"2014-07-06T17:40:00+00:00\",\"dateModified\":\"2025-03-04T18:45:13+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/#\\\/schema\\\/person\\\/bba546ac4d77da1fb51bc4030238e864\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/blog\\\/2014\\\/07\\\/06\\\/wpdev-talking-to-xml-web-services\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/simpkins.social\\\/cliff\\\/blog\\\/2014\\\/07\\\/06\\\/wpdev-talking-to-xml-web-services\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/blog\\\/2014\\\/07\\\/06\\\/wpdev-talking-to-xml-web-services\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"WPDev: Talking to XML web services\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/#website\",\"url\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/\",\"name\":\"Cliff Simpkins\",\"description\":\"Personal site + blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/#\\\/schema\\\/person\\\/bba546ac4d77da1fb51bc4030238e864\",\"name\":\"cliff.simpkins\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/07b113647e819a448cfc8545b476db50a641b9d43808a2c399af84e724d078d2?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/07b113647e819a448cfc8545b476db50a641b9d43808a2c399af84e724d078d2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/07b113647e819a448cfc8545b476db50a641b9d43808a2c399af84e724d078d2?s=96&d=mm&r=g\",\"caption\":\"cliff.simpkins\"},\"url\":\"https:\\\/\\\/simpkins.social\\\/cliff\\\/blog\\\/author\\\/cliff-simpkins\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"WPDev: Talking to XML web services - Cliff Simpkins","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/","og_locale":"en_US","og_type":"article","og_title":"WPDev: Talking to XML web services - Cliff Simpkins","og_description":"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&hellip;","og_url":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/","og_site_name":"Cliff Simpkins","article_published_time":"2014-07-06T17:40:00+00:00","article_modified_time":"2025-03-04T18:45:13+00:00","author":"cliff.simpkins","twitter_card":"summary_large_image","twitter_misc":{"Written by":"cliff.simpkins","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/#article","isPartOf":{"@id":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/"},"author":{"name":"cliff.simpkins","@id":"https:\/\/simpkins.social\/cliff\/#\/schema\/person\/bba546ac4d77da1fb51bc4030238e864"},"headline":"WPDev: Talking to XML web services","datePublished":"2014-07-06T17:40:00+00:00","dateModified":"2025-03-04T18:45:13+00:00","mainEntityOfPage":{"@id":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/"},"wordCount":603,"articleSection":["Windows Phone"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/","url":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/","name":"WPDev: Talking to XML web services - Cliff Simpkins","isPartOf":{"@id":"https:\/\/simpkins.social\/cliff\/#website"},"datePublished":"2014-07-06T17:40:00+00:00","dateModified":"2025-03-04T18:45:13+00:00","author":{"@id":"https:\/\/simpkins.social\/cliff\/#\/schema\/person\/bba546ac4d77da1fb51bc4030238e864"},"breadcrumb":{"@id":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/simpkins.social\/cliff\/blog\/2014\/07\/06\/wpdev-talking-to-xml-web-services\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/simpkins.social\/cliff\/"},{"@type":"ListItem","position":2,"name":"WPDev: Talking to XML web services"}]},{"@type":"WebSite","@id":"https:\/\/simpkins.social\/cliff\/#website","url":"https:\/\/simpkins.social\/cliff\/","name":"Cliff Simpkins","description":"Personal site + blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/simpkins.social\/cliff\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/simpkins.social\/cliff\/#\/schema\/person\/bba546ac4d77da1fb51bc4030238e864","name":"cliff.simpkins","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/07b113647e819a448cfc8545b476db50a641b9d43808a2c399af84e724d078d2?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/07b113647e819a448cfc8545b476db50a641b9d43808a2c399af84e724d078d2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/07b113647e819a448cfc8545b476db50a641b9d43808a2c399af84e724d078d2?s=96&d=mm&r=g","caption":"cliff.simpkins"},"url":"https:\/\/simpkins.social\/cliff\/blog\/author\/cliff-simpkins\/"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/posts\/150","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/comments?post=150"}],"version-history":[{"count":1,"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/posts\/150\/revisions"}],"predecessor-version":[{"id":151,"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/posts\/150\/revisions\/151"}],"wp:attachment":[{"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/media?parent=150"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/categories?post=150"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/simpkins.social\/cliff\/wp-json\/wp\/v2\/tags?post=150"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}