<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>DK Development</title>
 <link href="https://dkdevelopment.net/atom.xml" rel="self"/>
 <link href="https://dkdevelopment.net"/>
 <updated>2026-04-21T07:50:44+00:00</updated>
 <id>https://dkdevelopment.net</id>
 <author>
   <name>Damian Karzon</name>
   <email>dkarzon@tboda.com</email>
 </author>

 
 <entry>
   <title>The Rise of the Engineering Agent Manager</title>
   <link href="https://dkdevelopment.net/rise-of-engineering-agent-manager//"/>
   <updated>2026-04-07T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/rise-of-engineering-agent-manager/</id>
   <content type="html">&lt;p&gt;There’s a conversation happening in every engineering org right now, whether it’s out loud or just quietly in people’s heads: &lt;em&gt;what exactly is my job now?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a long time, the path was well understood. Junior developers write code, senior developers write better code and review it, tech leads set patterns and mentor, and engineering managers coordinate people and delivery. Everyone had a lane. AI has blown that model up, not by replacing people, but by fundamentally changing where the value is.&lt;/p&gt;

&lt;p&gt;The engineers and leaders who are thriving right now aren’t the ones who are best at writing code. They’re the ones who are best at directing, reviewing, and shaping the work that AI agents are producing.&lt;/p&gt;

&lt;h3 id=&quot;from-producer-to-director&quot;&gt;From Producer to Director&lt;/h3&gt;

&lt;p&gt;Here’s the mental shift that took me a while to internalise: your job is no longer to be the best implementer. It’s to be the best decision-maker about what gets implemented and why.&lt;/p&gt;

&lt;p&gt;Think of it like the difference between being a craftsman and being an architect. A craftsman’s value is in their ability to produce the work with their hands. An architect’s value is in their ability to understand the brief, envision the outcome, and communicate that clearly enough for others (or now, agents) to execute it faithfully.&lt;/p&gt;

&lt;p&gt;The coding work itself hasn’t disappeared. There’s more of it than ever. But the constraint has shifted from &lt;em&gt;how fast can humans write code&lt;/em&gt; to &lt;em&gt;how well can humans define, review, and guide what agents produce&lt;/em&gt;. That changes everything about what a strong engineering leader looks like.&lt;/p&gt;

&lt;h3 id=&quot;architecture-strategy-vision-now-the-whole-job&quot;&gt;Architecture, Strategy, Vision: Now the Whole Job&lt;/h3&gt;

&lt;p&gt;When an agent can scaffold a feature in minutes, the bottleneck becomes the quality of what you gave it to work from. Vague requirements produce vague code. Poorly considered architecture decisions, when handed to an agent that will faithfully implement them at scale, produce large amounts of faithfully bad code.&lt;/p&gt;

&lt;p&gt;This is where Engineering Managers and tech leads are finding renewed purpose. Spending time deeply on:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;System design and architecture&lt;/strong&gt;: The decisions that are hard to reverse, that constrain everything downstream, that require experience and judgment.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Product strategy&lt;/strong&gt;: What should we actually be building? What’s the simplest version of this that delivers value?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Technical vision&lt;/strong&gt;: Where is the codebase going in 6 months? What patterns should agents be following? What should they never do?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Context documents&lt;/strong&gt;: More on this below, but writing the documentation that puts agents in the right headspace is now a core leadership skill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The engineers who are leaning into this are finding that their impact is multiplied. One person with a clear vision and a well-configured agent workflow can ship what used to take a team.&lt;/p&gt;

&lt;h3 id=&quot;controlling-agents-through-context&quot;&gt;Controlling Agents Through Context&lt;/h3&gt;

&lt;p&gt;One of the more interesting things about working with AI coding agents (tools like GitHub Copilot, Cursor, and others) is that they’re heavily influenced by the context you give them. This has spawned a new type of document that’s becoming a standard part of engineering workflows: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AGENTS.md&lt;/code&gt; file, custom instruction files, and project-scoped prompt documents.&lt;/p&gt;

&lt;p&gt;These documents are essentially your communication layer with your agents. A well-written &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AGENTS.md&lt;/code&gt; might define:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The coding style and conventions for the project&lt;/li&gt;
  &lt;li&gt;Which patterns to use and which to avoid&lt;/li&gt;
  &lt;li&gt;How to structure components, name things, and organise files&lt;/li&gt;
  &lt;li&gt;Testing expectations&lt;/li&gt;
  &lt;li&gt;Scope boundaries: what the agent should and shouldn’t touch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tech leads who are writing these documents well are discovering something important: it forces you to articulate things that usually live only in your head. The conventions that you’d catch in a code review but never wrote down anywhere. The architectural decisions that are obvious to you but invisible to a new team member, or an agent.&lt;/p&gt;

&lt;p&gt;There’s also a feedback loop here. When an agent produces something that misses the mark, the right response isn’t just to fix the output. It’s to update your context documents so the agent gets it right next time. This is a fundamentally different kind of engineering leadership work, and it’s a skill that takes practice.&lt;/p&gt;

&lt;h3 id=&quot;linear-and-the-agent-friendly-backlog&quot;&gt;Linear and the Agent-Friendly Backlog&lt;/h3&gt;

&lt;p&gt;Project management tooling is catching up fast. Linear has become the tool of choice for a lot of engineering teams, and it’s easy to see why when you start working in an AI-native way.&lt;/p&gt;

&lt;p&gt;Where a traditional Jira ticket might be a title and two sentences, Linear has nudged teams toward writing richer, more structured issue descriptions. And now with AI agents that can be pointed at a Linear ticket to execute on, the quality of that ticket has a direct impact on the quality of what gets built.&lt;/p&gt;

&lt;p&gt;The mental model is shifting from &lt;em&gt;assign this to a developer&lt;/em&gt; to &lt;em&gt;can an agent execute on this ticket as written?&lt;/em&gt; If the answer is no (too vague, missing acceptance criteria, or lacking technical context), that’s a signal the issue needs more work before it goes anywhere.&lt;/p&gt;

&lt;p&gt;For engineering managers and leads, this creates a new responsibility around backlog hygiene. Grooming a ticket used to be about making sure a human developer had enough information to get started. Now it’s about making sure that information is structured clearly enough that an agent can run with it autonomously, with a human reviewing the output rather than doing the work line by line.&lt;/p&gt;

&lt;p&gt;Some teams are even going further, using agents to draft tickets from higher-level briefs, then having leads review and refine those before they’re executed. The human judgment is still in the loop, just at a different stage.&lt;/p&gt;

&lt;h3 id=&quot;the-review-layer-is-the-new-craft&quot;&gt;The Review Layer Is the New Craft&lt;/h3&gt;

&lt;p&gt;If you’re an engineering leader and you’re worried that AI is devaluing your expertise, I’d push back on that. What’s changing is &lt;em&gt;where&lt;/em&gt; you apply it.&lt;/p&gt;

&lt;p&gt;The code review is becoming more important, not less. When agents are generating code, the review is where human expertise catches the subtle misalignments: the technically correct implementation that misses the intent, the approach that works for this feature but creates problems for the next one, the security concern that the agent didn’t have enough context to see coming.&lt;/p&gt;

&lt;p&gt;This requires:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Deep familiarity with the codebase and its constraints&lt;/li&gt;
  &lt;li&gt;Clear communication about &lt;em&gt;why&lt;/em&gt; something isn’t right, not just that it isn’t&lt;/li&gt;
  &lt;li&gt;The ability to update context documents so the same mistake doesn’t happen again&lt;/li&gt;
  &lt;li&gt;Trust in your own judgment about when to approve and when to push back&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the skills that separate a great engineering leader from a mediocre one, and they haven’t changed. They’ve just been relocated to a new part of the workflow.&lt;/p&gt;

&lt;h3 id=&quot;the-leaders-who-are-struggling&quot;&gt;The Leaders Who Are Struggling&lt;/h3&gt;

&lt;p&gt;It’s also worth being honest about where the friction is. Not everyone is finding this transition easy.&lt;/p&gt;

&lt;p&gt;The engineers who built their identity around being great implementers — who took pride in hammering out clean code quickly — are having to find a new source of professional satisfaction. That’s genuinely hard. The craft is real and it matters, and being asked to step back from it to direct others (or agents) doing it can feel like a demotion even when it isn’t.&lt;/p&gt;

&lt;p&gt;There’s also a learning curve to working effectively with agents that a lot of people underestimate. It’s not as simple as asking a question and accepting whatever comes back. It requires developing intuition for when to trust the output, when to scrutinise it, and how to give feedback that actually improves future results.&lt;/p&gt;

&lt;p&gt;The leaders who are investing time in building this intuition are pulling ahead. The ones who are treating AI tools as a productivity shortcut but not changing how they think about their role are finding the benefits much more limited.&lt;/p&gt;

&lt;h3 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h3&gt;

&lt;p&gt;If you’re an Engineering Manager or tech lead who’s still finding your footing with this shift, a few practical starting points:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Write an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AGENTS.md&lt;/code&gt; for one of your projects.&lt;/strong&gt; Even if it’s imperfect, the act of writing down your conventions is valuable regardless of agents.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Try completing a full feature with an agent&lt;/strong&gt;, staying in the director seat. Define the work clearly, review what it produces, iterate through feedback. Notice where you struggle to articulate what you want.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Audit your Linear (or equivalent) backlog.&lt;/strong&gt; Would an agent have enough context to work from these tickets? Where are the gaps?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Share the experience with your team.&lt;/strong&gt; The best teams right now are learning together, sharing prompt patterns that work, updating shared context docs based on what agents get wrong.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The shift is real and it’s happening fast. The good news is that the skills that make a great engineering leader (clear thinking, good judgment, strong communication, technical depth) are exactly what this new way of working demands. They just need to be applied in new places.&lt;/p&gt;

&lt;p&gt;The Engineering Agent Manager is already here. The question is whether you’re ready to step into that role.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using Schema.org structured data to improve SEO</title>
   <link href="https://dkdevelopment.net/seo-structured-data-2025//"/>
   <updated>2025-12-03T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/seo-structured-data-2025/</id>
   <content type="html">&lt;p&gt;Search engine optimization has long been a cornerstone of the web, continually evolving as search engines and open‑web initiatives shape how information is discovered.&lt;/p&gt;

&lt;p&gt;Today, the rise of AI tools and AI‑powered search is accelerating that evolution, making structured data more critical than ever. In this post, I’ll explore how adding schema.org markup can enrich your content, improve visibility across both traditional search and AI‑driven platforms, and ultimately create a better experience for users.&lt;/p&gt;

&lt;blockquote&gt;
    Schema.org is a set of extensible schemas that enables webmasters to embed structured data on their web pages for use by search engines and other applications. For more details, see the &lt;a href=&quot;https://schema.org&quot;&gt;homepage&lt;/a&gt;.
&lt;/blockquote&gt;

&lt;h4 id=&quot;why-use-structured-data&quot;&gt;Why Use Structured Data?&lt;/h4&gt;

&lt;p&gt;Adding structured data to your website provides several benefits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Rich Search Results&lt;/strong&gt;: Your content can appear with enhanced visuals in search results, including star ratings, images, prices, and availability information&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Better Click-Through Rates&lt;/strong&gt;: Rich snippets stand out in search results, leading to higher engagement&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Voice Search Optimization&lt;/strong&gt;: Search assistants use structured data to provide spoken answers&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Knowledge Graph Integration&lt;/strong&gt;: Your content can be featured in Google’s Knowledge Panel&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;AI Agent Compatibility&lt;/strong&gt;: Modern AI systems can better understand and utilise your content (more on this below)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;how-to-implement-structured-data&quot;&gt;How to Implement Structured Data&lt;/h4&gt;

&lt;p&gt;There are 3 main ways to include structured data in a website’s markup:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Microdata&lt;/li&gt;
  &lt;li&gt;JSON-LD&lt;/li&gt;
  &lt;li&gt;RDFa&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Microdata&lt;/strong&gt; adds additional attributes to HTML elements to identify the data on the page. The data is embedded directly within your existing HTML.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;article&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemscope&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemtype=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://schema.org/BlogPosting&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;headline&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;My Blog Post Title&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;author&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemscope&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemtype=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://schema.org/Person&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Damian Karzon&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;time&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;datePublished&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;datetime=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2025-12-04&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;December 4, 2025&lt;span class=&quot;nt&quot;&gt;&amp;lt;/time&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;articleBody&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;The content of the blog post goes here...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;JSON-LD&lt;/strong&gt; (JavaScript Object Notation for Linked Data) adds a JSON block to the page where the structured data is output in a single location. This is Google’s recommended format as it’s easier to implement and maintain.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;application/ld+json&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@context&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://schema.org&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;BlogPosting&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;headline&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;My Blog Post Title&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Damian Karzon&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;datePublished&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;2025-12-04&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;dateModified&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;2025-12-04&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://example.com/images/post-banner.jpg&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;publisher&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Organization&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;DK Development&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;logo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ImageObject&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://example.com/logo.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;RDFa&lt;/strong&gt; (Resource Description Framework in Attributes) like Microdata, adds additional attributes to HTML elements to identify the data on the page. It’s more verbose but offers greater flexibility.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;article&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;vocab=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://schema.org/&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;typeof=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;BlogPosting&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;headline&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;My Blog Post Title&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;author&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;typeof=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Person&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Damian Karzon&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;time&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;datePublished&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;datetime=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2025-12-04&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;December 4, 2025&lt;span class=&quot;nt&quot;&gt;&amp;lt;/time&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;articleBody&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;The content of the blog post goes here...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;which-format-should-you-use&quot;&gt;Which Format Should You Use?&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;JSON-LD is the recommended approach&lt;/strong&gt; for most implementations because:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;It’s easier to add and maintain (no need to modify existing HTML)&lt;/li&gt;
  &lt;li&gt;It keeps your markup cleaner&lt;/li&gt;
  &lt;li&gt;It’s Google’s preferred format&lt;/li&gt;
  &lt;li&gt;It can be dynamically generated server-side or via JavaScript&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;popular-schema-types&quot;&gt;Popular Schema Types&lt;/h4&gt;

&lt;p&gt;A comprehensive list of schema types can be found at &lt;a href=&quot;https://schema.org/docs/schemas.html&quot;&gt;schema.org/docs/schemas.html&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;The vocabulary currently consists of 792 Types, 1447 Properties, 15 Datatypes, 83 Enumerations and 445 Enumeration members.&lt;/blockquote&gt;

&lt;p&gt;Here are some of the most commonly used schema types:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Schema Type&lt;/th&gt;
      &lt;th&gt;Use Case&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Article/BlogPosting&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Blog posts and news articles&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Product&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;E-commerce product pages&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;LocalBusiness&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Physical business locations&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Organization&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Company information&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Person&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Individual profiles&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Recipe&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Cooking recipes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Event&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Upcoming events&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;FAQPage&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Frequently asked questions&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;HowTo&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Step-by-step guides&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Review&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Product or service reviews&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;BreadcrumbList&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Site navigation breadcrumbs&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;VideoObject&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Video content&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;ai-agents-and-structured-data&quot;&gt;AI Agents and Structured Data&lt;/h4&gt;

&lt;p&gt;With the rise of AI assistants like ChatGPT, Claude, Gemini, and others, structured data has taken on a new dimension of importance. Here’s how AI agents interact with schema.org markup:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhanced Content Understanding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI agents parse structured data to better understand the context and meaning of web content. When an AI encounters a page with proper schema markup, it can:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Accurately identify the type of content (article, product, recipe, etc.)&lt;/li&gt;
  &lt;li&gt;Extract key information like authors, dates, prices, and ratings&lt;/li&gt;
  &lt;li&gt;Understand relationships between entities on the page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;AI-Powered Search and Assistants&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many AI systems now power search experiences and virtual assistants:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt;: AI systems that search and synthesise information benefit from structured data to provide accurate, well-attributed responses&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Voice Assistants&lt;/strong&gt;: Siri, Alexa, and Google Assistant use structured data to answer questions directly&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;AI Search Engines&lt;/strong&gt;: Perplexity, Bing Copilot, and Google’s AI Overviews leverage schema markup to generate accurate summaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Agentic Web Browsing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As AI agents become more autonomous in browsing and interacting with websites:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Structured data helps agents understand page purpose and available actions&lt;/li&gt;
  &lt;li&gt;Schema types like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntryPoint&lt;/code&gt; can indicate how to interact with a service&lt;/li&gt;
  &lt;li&gt;Well-marked content is more likely to be correctly interpreted and cited&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practices for AI Compatibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To optimise your structured data for AI agents:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Be comprehensive&lt;/strong&gt;: Include as many relevant properties as possible&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Use accurate data&lt;/strong&gt;: AI systems may cross-reference your claims&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sameAs&lt;/code&gt; properties&lt;/strong&gt;: Link to authoritative sources (Wikipedia, social profiles)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;speakable&lt;/code&gt; schema&lt;/strong&gt;: Indicates content suitable for text-to-speech&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WebPage&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WebSite&lt;/code&gt; schemas&lt;/strong&gt;: Helps AI understand your site structure&lt;/li&gt;
&lt;/ol&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;application/ld+json&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@context&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://schema.org&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;WebSite&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;DK Development&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://dkdevelopment.net&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;potentialAction&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SearchAction&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://dkdevelopment.net/search?q={search_term_string}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;query-input&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;required name=search_term_string&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;testing-your-structured-data&quot;&gt;Testing Your Structured Data&lt;/h4&gt;

&lt;p&gt;Before deploying structured data to production, validate it using these tools:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://search.google.com/test/rich-results&quot;&gt;Google Rich Results Test&lt;/a&gt;&lt;/strong&gt;: Tests if your page is eligible for rich results&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://validator.schema.org/&quot;&gt;Schema.org Validator&lt;/a&gt;&lt;/strong&gt;: Validates your markup against the schema.org specification&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.google.com/webmasters/markup-helper/&quot;&gt;Google Structured Data Markup Helper&lt;/a&gt;&lt;/strong&gt;: Helps generate markup for your pages&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;a-real-world-blog-example&quot;&gt;A Real-World Blog Example&lt;/h4&gt;

&lt;p&gt;Here’s how I’ve implemented structured data on this very blog using JSON-LD:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;application/ld+json&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@context&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://schema.org&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;BlogPosting&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mainEntityOfPage&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;WebPage&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@id&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://dkdevelopment.net/seo-structured-data-2025/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;headline&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Using Schema.org structured data to improve SEO&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;How to add Schema.org markup to your websites to improve users search experience.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://dkdevelopment.net/img/Banners/book.jpg&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Damian Karzon&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://dkdevelopment.net&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;publisher&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Organization&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;DK Development&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;logo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ImageObject&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://dkdevelopment.net/img/favicon.ico&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;datePublished&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;2025-12-04&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;dateModified&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;2025-12-04&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;recap&quot;&gt;Recap&lt;/h4&gt;

&lt;p&gt;Structured data is no longer just about improving traditional search results—it’s becoming essential infrastructure for how AI systems understand and interact with web content. By implementing schema.org markup:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Choose JSON-LD&lt;/strong&gt; as your primary format for ease of implementation&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Start with the basics&lt;/strong&gt;: Add Article/BlogPosting schema to your blog posts&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Expand to business schemas&lt;/strong&gt;: Organization, LocalBusiness, and Person for your about pages&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Test thoroughly&lt;/strong&gt; before deployment using Google’s validation tools&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Think about AI&lt;/strong&gt;: Your structured data helps AI agents accurately represent your content&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As AI continues to transform how users discover and consume web content, well-structured data will become a competitive advantage—not just for SEO, but for ensuring your content is accurately understood and represented across an increasingly AI-mediated web.&lt;/p&gt;

&lt;h4 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://schema.org/Blog&quot;&gt;Schema.org Blog Type&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developers.google.com/search/docs/advanced/structured-data/article&quot;&gt;Google’s Article Structured Data Guide&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/philwareham/schema-microdata-examples/blob/main/blog.html&quot;&gt;Schema Microdata Examples on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>My Home Assistant Docker Compose file</title>
   <link href="https://dkdevelopment.net/my-home-assistant-docker-compose//"/>
   <updated>2022-05-19T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/my-home-assistant-docker-compose/</id>
   <content type="html">&lt;p&gt;Over the last few months I have been playing around with a Home Assistant instance in Docker to run all of my home automation and over time I have slowly added more and more to it (more integrations, more services, more devices, etc.).&lt;/p&gt;

&lt;p&gt;Some info about my setup before we get into it.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Host machine running Windows 10 Pro&lt;/li&gt;
  &lt;li&gt;Docker Desktop using WSL2 backend&lt;/li&gt;
  &lt;li&gt;.wslconfig configured with 30GB Ram and 5 Processors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since I don’t run Home Assistant Operating System I don’t have the ability to use the supervisor and install services through that which means I’ve had to setup my own docker containers for additional services.
The containers I have running here are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Home Assistant&lt;/strong&gt; - The standalone Home Assistant Core install&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt; - Database storage for Home Assistant recorder (instead of using filesystem)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Node Red&lt;/strong&gt; - Low-code programming tool for wiring up events&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Mosquitto&lt;/strong&gt; - An MQTT message broker (to allow devices to use a publish/subscribe model of messaging)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tasmoadmin&lt;/strong&gt; - Administration platform for Tasmota devices (to allow OTA updates of devices without direct internet access)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Chrony&lt;/strong&gt; - A Network Time Protocol (NTP) Server (to allow devices without internet access to synchronise time)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;InfluxDB&lt;/strong&gt; - A Scalable datastore for metrics, events, and real-time analytics (used for long term storage of sensor data)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Grafana&lt;/strong&gt; - Open source data visualisation platform (to create dashboards from the data in InfluxDB)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let’s take a look at the docker-compose.yml file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3.1&apos;&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;home-assistant&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;home-assistant&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;homeassistant/home-assistant:2022.5.4&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;localnet&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/c/local-docker/home-assistant/config:/config&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/c/local-docker/home-assistant/media:/media&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mosquitto&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;8123:8123&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1400:1400&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;TZ&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Australia/Brisbane&quot;&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;postgres&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;postgres&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;postgres:12.6&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;localnet&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;5432:5432&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;POSTGRES_DB&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;homeassistant&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;POSTGRES_USER&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ha_user&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;CrazyStr0ngPa$$word&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;nodered&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nodered&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nodered/node-red&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;localnet&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1880:1880&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/c/local-docker/home-assistant/nodered:/data&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;home-assistant&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mosquitto&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;TZ&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Australia/Brisbane&quot;&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;mosquitto&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mosquitto&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;eclipse-mosquitto&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;localnet&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1883:1883&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1884:1884&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/c/local-docker/home-assistant/mosquitto/config:/mosquitto/config&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/c/local-docker/home-assistant/mosquitto/data:/mosquitto/data&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/c/local-docker/home-assistant/mosquitto/log:/mosquitto/log&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;TZ&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Australia/Brisbane&quot;&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;tasmoadmin&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;tasmoadmin&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ghcr.io/tasmoadmin/tasmoadmin:v1.8.0&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;localnet&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;8124:80&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/c/local-docker/home-assistant/tasmoadmin:/data/tasmoadmin&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;chrony&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;chrony&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;cturra/ntp&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;localnet&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;NTP_SERVERS=time.windows.com&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;123:123&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;influxdb&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;influxdb&lt;/span&gt; 
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;influxdb:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;localnet&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DOCKER_INFLUXDB_INIT_MODE=setup&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;INFLUXDB_DB=home_assistant&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DOCKER_INFLUXDB_INIT_USERNAME=influx_user&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DOCKER_INFLUXDB_INIT_PASSWORD=CrazyStr0ngPa$$word&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DOCKER_INFLUXDB_INIT_ORG=ha-org&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DOCKER_INFLUXDB_INIT_BUCKET=ha-bucket&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;8086:8086&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/c/local-docker/home-assistant/influxdb:/var/lib/influxdb2&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;grafana&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;grafana&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;grafana/grafana:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;localnet&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;influxdb&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;GF_SECURITY_ADMIN_USER=grafana_user&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;GF_SECURITY_ADMIN_PASSWORD=CrazyStr0ngPa$$word&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;8125:3000&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/c/local-docker/home-assistant/grafana:/var/lib/grafana&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;localnet&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bridge&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s start with a few of the common parts to it.&lt;/p&gt;

&lt;h3 id=&quot;commons&quot;&gt;Commons&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;container_name&lt;/strong&gt; - I’ve given all of the containers specific names instead of the default naming of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;folder name&amp;gt;_&amp;lt;service name&amp;gt;_1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;networks&lt;/strong&gt; - All the containers have been added to a custom network called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localnet&lt;/code&gt; which is also defined at the top level with the driver set to bridge. This is to make sure all of the containers can properly talk to each other and get around some network oddities I was experiencing with my setup.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;restart&lt;/strong&gt; - All of the containers are also set to always restart so whenever docker starts up they will also startup. So if the host is every restarted the containers will come back automatically.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;depends_on&lt;/strong&gt; - I have a few containers that set the depends on to ensure other containers are successfully loaded before them but this isn’t necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now into the containers themselves…&lt;/p&gt;

&lt;h3 id=&quot;home-assistant&quot;&gt;home-assistant&lt;/h3&gt;
&lt;p&gt;The main Home Assistant Core image, here I have given it a specific version so that I can easily see which version I’m using and update when I need to. Using latest here would work as well but may need to make sure if pulls down latest instead of using the existing cached version.&lt;/p&gt;

&lt;p&gt;I also have setup some mapped volumes for this so I can keep my config files in a folder on the Windows host machine. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/c/local-docker/home-assistant/config:/config&lt;/code&gt; This one maps the Windows folder &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\local-docker\home-assistant\config&lt;/code&gt; to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/config&lt;/code&gt; directory within the container which is where the main config yaml files are kept. This allows me to more easily edit the config files from the host machine as well as persisting the config across rebuilds of the container. The other volume entry is for media which allows me to easily add media to the server for local playback on media players. The TZ environment variable here sets the timezone of the container to make sure it’s running in my local timezone.&lt;/p&gt;

&lt;h3 id=&quot;postgres&quot;&gt;postgres&lt;/h3&gt;
&lt;p&gt;I’ve gone with using a PostgreSQL instance here for the recorder because my home assistant container has it’s config folder as a mounted volume which on Windows has a bit of a performance hit and since I run these folders from my local C Drive I wanted to make sure my home assistant wasn’t slowing anything else running on the host machine too much. The recorder integration also supports MySQL, MariaDB and SQLite (default), more info here: &lt;a href=&quot;https://www.home-assistant.io/integrations/recorder/&quot;&gt;https://www.home-assistant.io/integrations/recorder/&lt;/a&gt;. The container I actually use is in a separate docker-compose file because I use it for other things as well but I included it here for completeness.&lt;/p&gt;

&lt;h3 id=&quot;nodered&quot;&gt;nodered&lt;/h3&gt;
&lt;p&gt;I am not setting a version for this image so it will just use the latest available when it is started (I haven’t had any issues with this so far). To connect the node red instance to home assistant you need to make sure you install the relevant home assistant packages:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;node-red-contrib-home-assistant&lt;/li&gt;
  &lt;li&gt;node-red-contrib-home-assistant-websocket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running node red in docker like this I found that installing packages from the UI didn’t install the latest from npm, because it installed them from the node red flows library (&lt;a href=&quot;https://flows.nodered.org/&quot;&gt;https://flows.nodered.org/&lt;/a&gt;). To install the latest versions here I had to run the npm install commands in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/data&lt;/code&gt; directory on the container itself.
This container has a volume setup for the /data directory so that I can backup the config and the flow json files and state is again persisted between rebuilds of the container.&lt;/p&gt;

&lt;h3 id=&quot;mosquitto&quot;&gt;mosquitto&lt;/h3&gt;
&lt;p&gt;Using the eclipse-mosquitto broker for MQTT (latest version works fine here) because it seems to be the best supported one for home assistant. For this one I have 3 different volumes to map the config, data and log directories to local folders, mainly so I can backup the config and ensure state is persistent between container rebuilds.&lt;/p&gt;

&lt;h3 id=&quot;tasmoadmin&quot;&gt;tasmoadmin&lt;/h3&gt;
&lt;p&gt;The image for this is no longer being uploaded to docker hub which is why it is pulling from github packages (ghcr.io/tasmoadmin/tasmoadmin:v1.8.0). The mapped volume here lets me keep a backup of my config and devices as well as helping to persist state between container rebuilds.&lt;/p&gt;

&lt;h3 id=&quot;chrony&quot;&gt;chrony&lt;/h3&gt;
&lt;p&gt;Not too much to configure for this one, there is an environment variable to set the time server to use (NTP_SERVERS) this can be set to what ever you want. I went with time.windows.com because my host machine is running windows and wanted to have the 2 running against the same time server.&lt;/p&gt;

&lt;h3 id=&quot;influxdb&quot;&gt;influxdb&lt;/h3&gt;
&lt;p&gt;Took me a little bit to decipher the documentation to get the right config I needed for this one since I hadn’t used influxdb before but got all the environment variables setup for it to work. Most of these are pretty straight forward for things like username, password, org and bucket, DOCKER_INFLUXDB_INIT_MODE=setup is used to ensure the automated setup is run the first time it is started. I also have a volume mapped here so that it persists between container builds mainly so that I don’t have to go about reconfiguring the integration with home assistant which requires the organisation id (not the same as the org environment variable) and the API token (generated through the automated setup).&lt;/p&gt;

&lt;h3 id=&quot;grafana&quot;&gt;grafana&lt;/h3&gt;
&lt;p&gt;This one I haven’t used too much yet but so this config may change as I use it more. At the moment I just have a mapped volume for backups and persistent state.&lt;/p&gt;

&lt;h2 id=&quot;bonus-content&quot;&gt;Bonus Content!&lt;/h2&gt;

&lt;p&gt;Since these services are all installed manually via docker I miss some of the integration points that comes with installing them through the HA supervisor. One of those is adding them to the side menu in home assistant, to do this we can make use of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;panel_iframe&lt;/code&gt; integration in home assistant, here is an example of that integration in configuration.yaml.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;panel_iframe&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;nodered&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Red&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;http://192.168.1.5:1880/&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mdi:file-tree&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;tasmoadmin&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;TasmoAdmin&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;http://192.168.1.5:8124/&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mdi:home-automation&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
</content>
 </entry>
 
 <entry>
   <title>Basic remote PC monitoring through Home Assistant</title>
   <link href="https://dkdevelopment.net/home-assistant-basic-pc-monitoring//"/>
   <updated>2021-12-15T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/home-assistant-basic-pc-monitoring/</id>
   <content type="html">&lt;p&gt;I’ve had a server running at home for a while to run various things for work and personal use and recently I put Home Assistant on it to have a play with.
If you haven’t heard of Home Assistant before it is an Open source home automation that puts local control and privacy first.&lt;/p&gt;

&lt;p&gt;One thing that I wanted to do was be able to monitor the server status itself, things like storage, memory usage and temps then feed that into Home Assistant so I could try out a notification pipeline. The problem was since my HA instance runs as a docker container it doesn’t have direct access to those APIs in windows to give out that kind of info.&lt;/p&gt;

&lt;p&gt;To get around this limitation I figured I had a look at a few tools that could surface that info as a Rest API that HA could consume but none did quite what I wanted easily so I decided to write my own light weight api to surface this data (also because it was fun). Then using the built in rest integration within HA I could set it up to read this data in as sensors.&lt;/p&gt;

&lt;p&gt;I did this in .net core using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.IO.DriveInfo.GetDrives()&lt;/code&gt; method which gets me all the details I need about the attached hard drives. Once I had that I filtered out to only should fixed drives (ie. non-removable storage) and mapped it to a model object so that I could output it as JSON without circular reference issues. I also outputted it as a dictionary where the drive letter was the key, this is to make it easier to pick up the specific drives later in HA.&lt;/p&gt;

&lt;p&gt;Here is the code for the controller:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Microsoft.AspNetCore.Mvc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.IO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Linq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;WinSysMon.Controllers&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HomeController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Controller&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;drives&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IActionResult&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Drives&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;DriveInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drives&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DriveInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetDrives&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;driveModels&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drives&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DriveType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DriveType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Fixed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DriveInfoModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToDictionary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;First&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;driveModels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DriveInfoModel&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AvailableFreeSpace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DriveFormat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TotalFreeSpace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TotalSize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VolumeLabel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DriveInfoModel&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DriveInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DriveInfoModel&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;AvailableFreeSpace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AvailableFreeSpace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;DriveFormat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DriveFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;TotalFreeSpace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TotalFreeSpace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;TotalSize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TotalSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;VolumeLabel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VolumeLabel&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once that was done and the API was working I needed to setup the sensors in HA using the rest integration. I setup 3 sensors per drive: availableFreeSpace, totalSize and volumeLabel which gave me enough info to do what I needed.
The rest integration can be configured via the yaml file in HA and it allows you to setup multiple sensors from a single endpoint it also lets you set the interval times and authentication.&lt;/p&gt;

&lt;p&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host.docker.internal&lt;/code&gt; as the url so that my HA instance running in docker can reference the host PC. Also doing some calculations on the values here since the API outputs the values in bytes so that I can just read them in as GB with 2 decimal places which is enough for me but can be changed easily.
Here is my yaml configuration for the rest sensors setting&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-liquid&quot; data-lang=&quot;liquid&quot;&gt;rest:
  - scan_interval: 600
    resource: http://host.docker.internal:55555/drives
    sensor:
      - name: &quot;Server Drive C availableFreeSpace&quot;
        value_template: &quot;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;availableFreeSpace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;round(2)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&quot;
        unit_of_measurement: GB
        
      - name: &quot;Server Drive C totalSize&quot;
        value_template: &quot;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;totalSize&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;round(2)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&quot;
        unit_of_measurement: GB
        
      - name: &quot;Server Drive C volumeLabel&quot;
        value_template: &quot;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;volumeLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&quot;
        

      - name: &quot;Server Drive D availableFreeSpace&quot;
        value_template: &quot;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;availableFreeSpace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;round(2)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&quot;
        unit_of_measurement: GB
        
      - name: &quot;Server Drive D totalSize&quot;
        value_template: &quot;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;totalSize&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;round(2)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&quot;
        unit_of_measurement: GB
        
      - name: &quot;Server Drive D volumeLabel&quot;
        value_template: &quot;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;volumeLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This will add some new entities to Home Assistant for us which look something like this in the dev tools.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/posts/2021/ha-deventities.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now that we have the sensor data in HA we can start using it, for now I have put it into a lovelace dashboard but it can also be used in automation rules and setup as triggers etc.
I created a simple gauge card to test it setting severity with red as under 10%, orange as under 50% and green over 50%.&lt;/p&gt;

&lt;table style=&quot;width: 100%;&quot;&gt;
  &lt;tr&gt;
    &lt;td&gt;
      
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-liquid&quot; data-lang=&quot;liquid&quot;&gt;type: gauge
entity: sensor.server_drive_c_availablefreespace
min: 0
max: 233
severity:
  green: 115
  yellow: 23
  red: 0
needle: true
name: &apos;C: Drive Usage&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

    &lt;/td&gt;
    &lt;td style=&quot;text-align: center;&quot;&gt;
      &lt;img src=&quot;/img/posts/2021/ha-drives.png&quot; /&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;From here next steps would be to look at integrating more sensors into the pipeline such as memory and temperature which can be done by querying with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Manamgent.ManagementObjectSearcher&lt;/code&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Google Lighthouse CI Server Automation</title>
   <link href="https://dkdevelopment.net/lighthouse-ci-server-automation//"/>
   <updated>2021-09-28T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/lighthouse-ci-server-automation/</id>
   <content type="html">&lt;p&gt;Website performance is one of those things that is “important” to everyone but it is sometime hard to test and keep track of the results in a way that is easy to navigate and doesn’t require too much effort. Recently it has become even more important for SEO (Search Engine Optimization) with the big search engines starting to use these metrics more to affect ranking (See: &lt;a href=&quot;https://developers.google.com/search/docs/advanced/experience/page-experience&quot;&gt;Understanding page experience in Google Search results&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Google Lighthouse is a well known performance testing tool for websites that is built into Google Chrome and used by &lt;a href=&quot;https://developers.google.com/speed/pagespeed/insights&quot;&gt; Google PageSpeed Insights&lt;/a&gt;. But there is also &lt;a href=&quot;https://github.com/GoogleChrome/lighthouse-ci&quot;&gt;Lighthouse CI&lt;/a&gt; which is an open source CLI tool for automating running lighthouse for a CI/CD environment.&lt;/p&gt;

&lt;p&gt;Lighthouse CI also has a server component that let’s you save reports and compare them which can be very useful.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/posts/2021/lhci1.gif&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To setup the Lighthouse CI server through docker there are 3 parts to it.&lt;/p&gt;

&lt;h5 id=&quot;dockerfile&quot;&gt;Dockerfile&lt;/h5&gt;

&lt;p&gt;Setup the docker image to run the Lighthouse CI server with the appropriate config.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;err&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;node:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-buster-slim&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/usr/src/lhci&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;package.json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;RUN&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;npm&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;lighthouserc.json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;EXPOSE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;CMD&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;npm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h5 id=&quot;packagejson&quot;&gt;package.json&lt;/h5&gt;

&lt;p&gt;The package.json file used to install the libraries and configure the server start.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lhci&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0.0.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lhci server --config=./lighthouserc.json&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@lhci/cli&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^0.8.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@lhci/server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^0.8.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mysql2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^2.1.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;pg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^7.12.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;pg-hstore&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^2.3.3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sqlite3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^4.0.6&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h5 id=&quot;lighthousercjson&quot;&gt;lighthouserc.json&lt;/h5&gt;

&lt;p&gt;The configuration file for the server, using PostgreSQL storage and daily CRON task to collect reports from PageSpeed Insights.
Check out the &lt;a href=&quot;https://github.com/GoogleChrome/lighthouse-ci/blob/main/docs/server.md&quot;&gt;Lighthouse CI Server docs&lt;/a&gt; for more info on this.
To enable the PageSpeed Insights cron task you will need to get an API Key from the &lt;a href=&quot;https://developers.google.com/speed/docs/insights/v5/get-started&quot;&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ci&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;storage&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;storageMethod&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sql&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sqlDialect&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;postgres&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sqlConnectionUrl&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;postgres://lhci_user:&amp;lt;password&amp;gt;@host.docker.internal:5432/lighthouseci_db&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;basicAuth&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;username&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;damian&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;PASSWORD&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;psiCollectCron&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;psiApiKey&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;psiApiKey&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sites&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;urls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://dkdevelopment.net/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://dkdevelopment.net/2019/05/25/working-remotely/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://dkdevelopment.net/resume/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;schedule&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0 0 * * *&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;projectSlug&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dkdevelopment.net&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once the server is up and running you then need to create a project on the server, to do this run: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lhci wizard&lt;/code&gt; to create a new project on the server and answer the questions it asks.
Save the tokens it generates (you will need these later).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/posts/2021/lhci-wizard.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;With the project setup and the PSI CRON tasks running you will then be able to see the daily reports coming in with the ability to compare reports over time.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/posts/2021/lhci-compare.jpg&quot; /&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Tips and tricks for Github Pages</title>
   <link href="https://dkdevelopment.net/tips-and-tricks-for-github-pages//"/>
   <updated>2020-07-26T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/tips-and-tricks-for-github-pages/</id>
   <content type="html">&lt;p&gt;This blog has been hosted on Github Pages for a long time, a very very long time, according to my git history since Feb 2012 (before that it was on Wordpress).&lt;/p&gt;

&lt;p&gt;I decided to make the change for a few reasons:&lt;br /&gt;
-To learn something new (Jekyll/Liquid were new to me)&lt;br /&gt;
-Have it feel more like a dev blog (writing posts in a dev IDE pushing to git etc.)&lt;br /&gt;
-Also the Pretzel Code52 project had just kicked off and I was interested in getting involved in that (&lt;a href=&quot;https://github.com/Code52/pretzel&quot;&gt;https://github.com/Code52/pretzel&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Now, 8 years later I am trying to get into blogging again so I am breathing new life into my Github Pages blog as well as building a new website for a podcast using Github Page so I thought I’d share some of the interesting things it can do.&lt;/p&gt;

&lt;h4&gt;Docker&lt;/h4&gt;
&lt;p&gt;I’m not a ruby developer and I didn’t want to have to install all of the ruby dev tools just to be able to add blog posts. Previously I was using a prebuilt version of pretzel locally which worked pretty well, there were a few things that worked differently or were not supported but I got by. After doing a fair bit of work with docker I figured I should just be able to run jekyll on docker, run the same version that runs on Gihub Pages without all the overhead.&lt;/p&gt;

&lt;p&gt;Luckily there are already github pages images setup so I didn’t need to do much to get this working, the one I went with is &lt;a href=&quot;https://github.com/Starefossen/docker-github-pages&quot;&gt;Starefossen/docker-github-pages&lt;/a&gt;. After finding that it was as easy as creating a powershell script to run it, which also mounts the directory to the docker container so it will auto update when changes are made.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-powershell&quot; data-lang=&quot;powershell&quot;&gt;&lt;span class=&quot;n&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;${PWD}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;/usr/src/app&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1000:4000&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;starefossen/github-pages&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jekyll&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serve&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;/_site&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--drafts&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--watch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--force_polling&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0.0.0.0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;4000&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4&gt;For each loops&lt;/h4&gt;
&lt;p&gt;Github pages and Jekyll use the &lt;a href=&quot;https://jekyllrb.com/docs/liquid/&quot;&gt;Liquid templating language&lt;/a&gt; which lets you do some fun things, one of them is for loops. The below code loops through the posts on the site (getting the first 12) to display links for each. &lt;code&gt;{% for post in site.posts limit: 12 %}&lt;/code&gt; - &lt;code&gt;site.posts&lt;/code&gt; being the collection to iterate over. &lt;code&gt;for post in&lt;/code&gt; defines a post as the individual item being iterated. &lt;code&gt;limit: 12&lt;/code&gt; sets the loop to only iterate over the first 12 items, this can also be used with &lt;code&gt;offset: 12&lt;/code&gt; which sets the iteration to start at item 12 in the collection.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;{% for post in site.posts limit: 12 %}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ post.url }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        {{ post.title }}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
{% endfor %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4&gt;Combine and Minify CSS&lt;/h4&gt;
&lt;p&gt;This one is a bit of a hack but it allows you to combine and (somewhat) minify CSS files using some of the liquid templating. Starting with the &lt;a href=&quot;https://www.rubydoc.info/github/Shopify/liquid/Liquid/Capture&quot;&gt;&lt;strong&gt;capture block&lt;/strong&gt;&lt;/a&gt; which lets you store a result in a variable without rendering it. Using the capture we then include the relevant css files inside the capture here using the &lt;a href=&quot;https://jekyllrb.com/docs/includes/&quot;&gt;&lt;strong&gt;include_relative&lt;/strong&gt;&lt;/a&gt; tag. Finally we render the newly captured variable making sure to strip out the new lines and multiple spaces.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;permalink&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;dkdev&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.min.css&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%-&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;capture&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;sitecss&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;include_relative&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;bootstrap.min.css&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;include_relative&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;fontawesome-free.min.css&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;include_relative&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;clean-blog.css&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%-&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;endcapture&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;{-&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;sitecss&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;strip_newlines&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;  &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4&gt;Data files&lt;/h4&gt;
&lt;p&gt;Jekyll allows you to add other &lt;a href=&quot;https://jekyllrb.com/docs/datafiles/&quot;&gt;data files&lt;/a&gt; that can be used by various pages. These are just yml, json or csv files that can be put in the _data folder that can be accessed from any page or layout using site.data.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
    &lt;pre&gt;
&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Phili J Fry&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Delivery Boy&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Bender&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Company Chef&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Turanga Leela&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Captain&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;John Zoidberg&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Staff doctor&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;This data file can then be used by a for loop to display all the items:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;{% for character in site.data.characters %}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        {{ character.name }} - {{ character.title }}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
{% endfor %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4&gt;Syntax Highlighting&lt;/h4&gt;
&lt;p&gt;Github Pages has built in syntax highlighting that uses the &lt;a href=&quot;https://github.com/rouge-ruby/rouge&quot;&gt;Rouge Ruby syntax highlighter&lt;/a&gt; library.
It let’s you wrap your code with &lt;code&gt;{% highlight %}&lt;/code&gt; and &lt;code&gt;{% endhighlight %}&lt;/code&gt; and it will do some formatting with it which allows you to easily style it.
All you need to do is include a rouge or pygments compatible stylesheet.&lt;/p&gt;

&lt;p&gt;Here is what mine looks like for reference: &lt;a href=&quot;https://dkdevelopment.net/css/pygments_style.css&quot;&gt;https://dkdevelopment.net/css/pygments_style.css&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Getting started with Singer and Docker</title>
   <link href="https://dkdevelopment.net/2020/06/14/singer-io-with-docker//"/>
   <updated>2020-06-14T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2020/06/14/singer-io-with-docker/</id>
   <content type="html">&lt;p&gt;I’ve been doing a lot of work with data recently and I wanted a way to be able to join some of our platform data to our traffic data from Google Analytics.&lt;/p&gt;

&lt;p&gt;After trying a few methods to get data out of Google Analytics into our PostgreSQL database with not much success I discovered &lt;a href=&quot;https://singer.io&quot;&gt;singer.io&lt;/a&gt; a “Simple, Composable, Open Source ETL” tool. So I started playing around with the Google Analytics tap and the PostgreSQL target (&lt;a href=&quot;https://www.singer.io/tap/google-analytics/postgresql/&quot;&gt;https://www.singer.io/tap/google-analytics/postgresql/&lt;/a&gt;). After a lot of digging through various documentations and source code I was able to get it working!&lt;/p&gt;

&lt;p&gt;Now that I have it running it was time to try and automate it somehow, to do this I tried to set it up as a docker container that way it can be run in the cloud (In our case AWS) on a schedule to pull in data daily from Google Analytics.&lt;/p&gt;

&lt;p&gt;Here is the Docker file that puts it all together.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-docker&quot; data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; python:3.7.6-stretch&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;singer-target-postgres

&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ./tap-google-analytics-master/ ./external/tap-google-analytics-master/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; /external/tap-google-analytics-master&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; .

&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; /&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ./singer/tap_google-analytics_config.json ./tap_google-analytics_config.json&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ./singer/client_secrets.json ./client_secrets.json&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ./singer/tap_google-analytics_reports.json ./tap_google-analytics_reports.json&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ./singer/target_postgres_config.json ./target_postgres_config.json&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;CMD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; tap-google-analytics -c ./tap_google-analytics_config.json | target-postgres -c ./target_postgres_config.json &amp;gt;&amp;gt; state.json&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A few things here to call out to get this working. Installing the PostgreSQL target was straight forward but for the Google Analytics tap I used an unofficial library and built it from the source at &lt;a href=&quot;https://gitlab.com/meltano/tap-google-analytics&quot;&gt;https://gitlab.com/meltano/tap-google-analytics&lt;/a&gt;. After that we have the various config files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tap_google-analytics_config.json&lt;/strong&gt; This is the config for the Google Analytics tap, key file location is name of the config file that details the service account credentials. The reports property is a json file that defines the reports to pull from Google Analytics. The start date and end date here define the date range to pull the report data for.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;key_file_location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;client_secrets.json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;view_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;111111111&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;reports&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;tap_google-analytics_reports.json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;start_date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2020-06-01T00:00:00Z&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;end_date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2020-06-15T00:00:00Z&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;client_secrets.json&lt;/strong&gt; this file contains the service account credentials, to get these follow the instructions defined in &lt;a href=&quot;https://gitlab.com/meltano/tap-google-analytics#creating-service-account-credentials&quot;&gt;https://gitlab.com/meltano/tap-google-analytics#creating-service-account-credentials&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tap_google-analytics_reports.json&lt;/strong&gt; this file defines the report data being pulled from Google Analytics. A full list of the available dimensions and metrics can be found here: &lt;a href=&quot;https://ga-dev-tools.appspot.com/dimensions-metrics-explorer/&quot;&gt;https://ga-dev-tools.appspot.com/dimensions-metrics-explorer/&lt;/a&gt;. Here is an example of a report for pageviews.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ga_pageviews&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;dimensions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ga:date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ga:pagePath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ga:source&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ga:medium&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ga:sourceMedium&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;metrics&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ga:pageviews&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;target_postgres_config.json&lt;/strong&gt; This file is the config for the PostgreSQL target, mostly straight forward connection config.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;postgres_host&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;localhost&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;postgres_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5432&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;postgres_database&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ga_data&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;postgres_username&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;db_user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;postgres_password&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;db_treasure&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;postgres_schema&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;public&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;after_run_sql&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now that we have everything setup to run in docker to truly automate this all that is left to do is being able to update the start and end date properties in the Google Analytics config file dynamically. This can be done with a bit of bash.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Working Remotely (and how)</title>
   <link href="https://dkdevelopment.net/2019/05/25/working-remotely//"/>
   <updated>2019-05-25T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2019/05/25/working-remotely/</id>
   <content type="html">&lt;p&gt;I work remotely and have been full time for over 6 months now and I wanted to take some time to talk about my experience with it. I quite often joke about this, for example here is a post from my Instagram after my 2nd week at another fully remote workplace.&lt;/p&gt;

&lt;blockquote class=&quot;instagram-media2&quot; style=&quot; background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; margin-bottom: 12px; max-width:540px; min-width:326px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);&quot;&gt;
    &lt;div style=&quot;padding:16px;&quot;&gt;
        &lt;div style=&quot; display: flex; flex-direction: row; align-items: center;&quot;&gt;
            &lt;div style=&quot;background-color: #F4F4F4; border-radius: 50%; flex-grow: 0; height: 40px; margin-right: 14px; width: 40px;&quot;&gt;
                &lt;a href=&quot;https://www.instagram.com/damiankarzon/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
                    &lt;img style=&quot;border-radius: 50%;&quot; src=&quot;https://pbs.twimg.com/profile_images/721583338671058944/M83ceTNZ_200x200.jpg&quot; alt=&quot;damiankarzon&quot; /&gt;
                &lt;/a&gt;
            &lt;/div&gt;
            &lt;div style=&quot;display: flex; flex-direction: column; flex-grow: 1; justify-content: center;&quot;&gt;
                &lt;div style=&quot;border-radius: 4px; flex-grow: 0; height: 14px; margin-bottom: 12px; width: 100px;&quot;&gt;
                    &lt;a style=&quot;color: #000; font-weight: 500; font-size: 14px;&quot; href=&quot;https://www.instagram.com/damiankarzon/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
                        damiankarzon
                    &lt;/a&gt;
                &lt;/div&gt;
                &lt;div style=&quot;border-radius: 4px; flex-grow: 0; height: 14px; width: 60px;&quot;&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div style=&quot;padding-top: 8px;&quot;&gt;
            &lt;a href=&quot;https://www.instagram.com/p/BuxJFmmBHOi/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
                &lt;img src=&quot;/img/posts/2019-05/work-remotely.png&quot; alt=&quot;Damian working from home&quot; /&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div style=&quot;display: flex; flex-direction: row; align-items: center;&quot;&gt;
            &lt;a href=&quot;https://www.instagram.com/p/BuxJFmmBHOi/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
                &lt;div style=&quot;background-color: #EEEEEE; border-radius: 50%; height: 12.5px; width: 12.5px; transform: translateX(0px) translateY(7px);&quot;&gt;
                &lt;/div&gt;
                &lt;div style=&quot;background-color: #EEEEEE; height: 12.5px; transform: rotate(-45deg) translateX(3px) translateY(1px); width: 12.5px; flex-grow: 0; margin-right: 14px; margin-left: 2px;&quot;&gt;
                &lt;/div&gt;
                &lt;div style=&quot;background-color: #EEEEEE; border-radius: 50%; height: 12.5px; width: 12.5px; transform: translateX(9px) translateY(-18px);&quot;&gt;
                &lt;/div&gt;
            &lt;/a&gt;
            &lt;a href=&quot;https://www.instagram.com/p/BuxJFmmBHOi/&quot; target=&quot;_blank&quot; style=&quot;margin-left: 8px;&quot; rel=&quot;noopener&quot;&gt;
                &lt;div style=&quot; background-color: #EEEEEE; border-radius: 50%; flex-grow: 0; height: 20px; width: 20px;&quot;&gt;
                &lt;/div&gt;
                &lt;div style=&quot; width: 0; height: 0; border-top: 2px solid transparent; border-left: 6px solid #EEEEEE; border-bottom: 2px solid transparent; transform: translateX(16px) translateY(-4px) rotate(30deg)&quot;&gt;
                &lt;/div&gt;
            &lt;/a&gt;
            &lt;a href=&quot;https://www.instagram.com/p/BuxJFmmBHOi/&quot; target=&quot;_blank&quot; style=&quot;margin-left: auto;&quot; rel=&quot;noopener&quot;&gt;
                &lt;div style=&quot; width: 0px; border-top: 8px solid #EEEEEE; border-right: 8px solid transparent; transform: translateY(16px);&quot;&gt;
                &lt;/div&gt;
                &lt;div style=&quot; background-color: #EEEEEE; flex-grow: 0; height: 12px; width: 16px; transform: translateY(-4px);&quot;&gt;
                &lt;/div&gt;
                &lt;div style=&quot; width: 0; height: 0; border-top: 8px solid #EEEEEE; border-left: 8px solid transparent; transform: translateY(-4px) translateX(8px);&quot;&gt;
                &lt;/div&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;p style=&quot;font-family:Arial,sans-serif; font-size:14px; line-height:16px; margin-bottom:0; margin-top:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;&quot;&gt;
            &lt;a href=&quot;https://www.instagram.com/damiankarzon/&quot; style=&quot;font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:16px;&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; Damian Karzon&lt;/a&gt; (@damiankarzon) on &lt;time style=&quot; font-family:Arial,sans-serif; font-size:14px; line-height:17px;&quot; datetime=&quot;2019-03-09T00:42:34+00:00&quot;&gt;Mar 8, 2019 at 4:42pm PST&lt;/time&gt;&lt;/p&gt;
        &lt;p style=&quot; margin:0;&quot;&gt;
            &lt;a href=&quot;https://www.instagram.com/p/BuxJFmmBHOi/&quot; style=&quot; color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:16px; text-decoration:none; word-wrap:break-word;&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;What people think of when I say I work from home vs. what it&amp;#39;s actually like.&lt;/a&gt;
        &lt;/p&gt;
    &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;But this is actually something I take very seriously and I am constantly asked about it. When I tell people I work from home they often ask me a question like &lt;em&gt;“How often do you have to go into the office?”&lt;/em&gt; or &lt;em&gt;“Where is their head office?”&lt;/em&gt;. My current workplace&lt;strong&gt;&lt;em&gt;has no office&lt;/em&gt;&lt;/strong&gt;, none at all. The entire company works remotely which is sometimes a strange concept for people.&lt;/p&gt;

&lt;p&gt;When I first started working remotely there were a few things that I was worried about:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Distractions&lt;/li&gt;
  &lt;li&gt;Cabin fever&lt;/li&gt;
  &lt;li&gt;Isolation&lt;/li&gt;
  &lt;li&gt;Work-life balance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, this post is specifically about my experience with remote work and, as I have learned throughout this time, everyone is different and depending on personalities are affected in different ways when it comes to this sort of thing.&lt;/p&gt;

&lt;h4 id=&quot;distractions&quot;&gt;Distractions&lt;/h4&gt;
&lt;p&gt;When I first started I thought the distractions would be a big problem for me (from past experience working from home in a non-full time way) so I set out to make sure I could minimise it. The main thing I did for this was to separate my home and work life both physically and mentally. I had a spare room at my place which I have converted into my home office that I use exclusively for working, I also have a dedicated work computer that I don’t use for anything else (ie. no games on it). To separate my home and work life mentally I try to go for a walk every day when I finish work, this helps to break up the work day from the non-work day (it’s also good to get some exercise in).&lt;/p&gt;

&lt;h4 id=&quot;cabin-fever&quot;&gt;Cabin fever&lt;/h4&gt;
&lt;p&gt;This wasn’t something I had actually considered when I started since I am quite comfortable staying at home for long periods of time. However the problem came up often when I found myself being stuck in a problem that I couldn’t solve. I would start to get irritated very easily by my surroundings and not being able to solve the problem in front of me so I would end up walking up and down the hallway for no reason. In this situation now I quite often turn to someone else on the team and jump of a quick call just to talk things out or I leave the house and go for a walk to get some fresh air.&lt;/p&gt;

&lt;h4 id=&quot;isolation&quot;&gt;Isolation&lt;/h4&gt;
&lt;p&gt;I often hear people talk about isolation being their biggest problem when it comes to working remotely but this hasn’t been a massive problem for me, probably due to living alone for the last 6 years. This is also helped by the virtual meetings we have which are all video calls and always start with a bit of a chat before getting into business. A great example of this is our weekly whole company meetings where we start by everyone having a chance to share something personal (maybe they did something exciting on the weekend or during the week) or they can share a learning from the previous week.&lt;/p&gt;

&lt;h4 id=&quot;work-life-balance&quot;&gt;Work-life balance&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;“Do you find yourself working more since it’s all just there?”&lt;/em&gt; or &lt;em&gt;“Do you sometimes just go and watch tv instead of working?”&lt;/em&gt; other questions I sometimes get asked. Both are on opposite sides of the work-life balance, on one hand you have the potential to over work since it is so close and on the other you could do no work at all because you are not confined to an office. My answer to both of these questions is normally &lt;em&gt;“Yes but…”&lt;/em&gt;, yes sometimes I do find myself working more, yes sometimes I do take a random break during the day if I’m feeling drained or stuck. It’s all about having the balance between the 2, it is much easier when working from home to over work or to under work but if you are motivated to do the work and have the discipline to keep working when you need to then you won’t have a problem. Motivation can be hard to find sometimes so it’s important to have work that you enjoy and are passionate about and to have a team that work well together. It is also important to remember that no job is awesome all the time and work will sometimes get you down but you need to keep at it anyway and work on making it better where you can.&lt;/p&gt;

&lt;h4 id=&quot;environment&quot;&gt;Environment&lt;/h4&gt;

&lt;p&gt;I have put a lot a lot of time, effort and investment into getting my home office setup and it’s at a point where I am more productive there than any office I have ever worked at.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Desk: SKARSTA sit/stand desk from IKEA (120x70 cm)&lt;/li&gt;
  &lt;li&gt;Chair: DX Racer Classic Series&lt;/li&gt;
  &lt;li&gt;Laptop: Microsoft Surface Book 2 (13” i7, 16GB Ram, 512GB SSD) with Surface dock&lt;/li&gt;
  &lt;li&gt;Monitor: Dell P2715Q 27” 4K&lt;/li&gt;
  &lt;li&gt;Audio: Steelseries Arctis 3 Bluetooth headset &amp;amp; JBL Charge 2 Bluetooth speaker&lt;/li&gt;
  &lt;li&gt;Keyboard: Steelseries Apex 350&lt;/li&gt;
  &lt;li&gt;Mouse: Steelseries Rival 110&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;tools&quot;&gt;Tools&lt;/h4&gt;

&lt;p&gt;It is also super important to find the right tools and team process to be able to work remotely. The majority of our communication is text based and for that we use Slack mostly (some emails here and there when dealing with external parties).
Sometimes it’s harder to communicate things over text, when this happens we tend to jump on a quick call using either a phone call, Slack call or a Zoom video call.
We currently run a “scrum-like” development process which includes daily virtual stand-ups, for this we use Zoom. We also use video calls for larger team meetings such as the weekly whole company or product team meetings, this makes discussions much easier and allows people to share screens if required.&lt;/p&gt;

&lt;p&gt;There are also times when the team (or at least part of the team) will meet up in person, for example the Brisbane dev team try to get together once a month and spend the day working together, this is either at a co-working space or a shared space (such as a library). There are also times when all of the workers in Brisbane will get together for a team lunch, this greatly heaps everyone get to know each other more and to feel more comfortable with each other.&lt;/p&gt;

&lt;p&gt;Well that’s enough ramblings from me about working remotely, let me know your thoughts on it or if you have any questions feel free to reach out to me (&lt;a href=&quot;https://twitter.com/dkarzon&quot;&gt;@dkarzon&lt;/a&gt; on Twitter).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Building a Discord voice bot with Discord.NET</title>
   <link href="https://dkdevelopment.net/2019/02/18/discord-voice-bot//"/>
   <updated>2019-02-18T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2019/02/18/discord-voice-bot/</id>
   <content type="html">&lt;p&gt;
    I&apos;ve been playing around with the Discord api recently, I wanted to see what could actually be done with it.
    I set a goal to make a discord bot that slightly annoys people by joining voice channels and randomly say Zapp Brannigan quotes.
&lt;/p&gt;

&lt;p&gt;
    For those who don&apos;t know Discord is an: &lt;blockquote&gt;All-in-one voice and text chat for gamers that&apos;s free, secure, and works on both your desktop and phone. - &lt;a href=&quot;https://discordapp.com/&quot;&gt;https://discordapp.com/&lt;/a&gt;&lt;/blockquote&gt;
&lt;/p&gt;

&lt;p&gt;
    I got started with &lt;a href=&quot;https://github.com/discord-net/Discord.Net&quot;&gt;Discord.NET&lt;/a&gt; and was able to get the bot connected very quickly. Discord.NET is an unofficial .NET API wrapper for discord which seem to be the most popular and widely used library for it so I went with it. Be sure to check out the &lt;a href=&quot;https://discord.foxbot.me/docs/&quot;&gt;documentation&lt;/a&gt; for details. For this to work with voice connections there are a few native dlls that you need to download and put with your application. These are simple enough to get from the &lt;a href=&quot;https://discord.foxbot.me/docs/guides/voice/sending-voice.html&quot;&gt;voice documentation&lt;/a&gt; (or check out my full source link at the end).
&lt;/p&gt;
&lt;p&gt;
    First thing you need to do is get an instance of &lt;strong&gt;DiscordSocketClient&lt;/strong&gt; for my project I am doing a .NET Core 2.2 console app with the built in dependency injection.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;_discord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_services&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GetRequiredService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DiscordSocketClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_discord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LoginAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TokenType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_botToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_discord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;StartAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That is all the code you need to have your bot connect to discord!&lt;/p&gt;

&lt;p&gt;
    I wanted my bot to detect when a user joined a voice channel and connect to that channel (if it wasn&apos;t already). To do that I used the &lt;strong&gt;UserVoiceStateUpdated&lt;/strong&gt; event on the DiscordSocketClient which can tell us when a users voice state updates (join/leave/move voice channels).
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Add this before calling StartAsync&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;_discord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserVoiceStateUpdated&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OnVoiceStateUpdated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The code to handle the event then looks like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnVoiceStateUpdated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SocketUser&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SocketVoiceState&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SocketVoiceState&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Check if this was a non-bot user joining a voice channel&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsBot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VoiceChannel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VoiceChannel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;ConnectToVoice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VoiceChannel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ConnectToVoice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SocketVoiceChannel&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voiceChannel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voiceChannel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$&quot;Connecting to channel &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voiceChannel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voiceChannel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ConnectAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$&quot;Connected to channel &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voiceChannel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;blocknote&quot;&gt;Important to note here is that we don&apos;t await ConnectToVoice, this is because if we await that call from inside the UserVoiceStateUpdated event it will cause a deadlock and never return from connecting to the voice channel.&lt;/div&gt;

&lt;p&gt;Now we are connecting to a voice channel when we detect a user joins it so lets look at having the bot actually send audio through. To do this the documentation for the library has an example using ffmpeg to read the sound files and pipes that into a stream that then gets sent to Discord.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;psi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProcessStartInfo&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;FileName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ffmpeg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Arguments&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$@&quot;-i &quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot; -ac 2 -f s16le -ar 48000 pipe:1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RedirectStandardOutput&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UseShellExecute&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ffmpeg&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;psi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ffmpeg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StandardOutput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreatePCMStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AudioApplication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Voice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CopyToAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;discord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FlushAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
    Here we start a new process passing in start info that opens up ffmpeg.exe (also included in the project) passing in a relative path to out sound file and a few other command line args to play the sound and pipe the output which we then copy into a stream into discord.
&lt;/p&gt;

&lt;p&gt;
    This is the basics of creating a voice capable discord bot with Discord.NET, for a more advanced implementation take a look at the full source for this project at &lt;a href=&quot;https://github.com/dkarzon/DiscordZapBot&quot;&gt;https://github.com/dkarzon/DiscordZapBot&lt;/a&gt;.
&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Responsive xaml properties in Xamarin.Forms</title>
   <link href="https://dkdevelopment.net/2018/06/24/xamarin-forms-responsive-xaml-properties//"/>
   <updated>2018-06-24T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2018/06/24/xamarin-forms-responsive-xaml-properties/</id>
   <content type="html">&lt;p&gt;I have been working on UI and UX a bit lately and trying to come up with views that are fluid across a whole range of device resolutions.&lt;/p&gt;

&lt;p&gt;Now, Xamarin.Forms does do a great job with UI but sometimes there are little things that you want to change on a per device or per resolution level.&lt;/p&gt;

&lt;p&gt;I noticed that there is a built in xaml helper called OnPlatform that lets you set xaml properties differently per platform so I dug into that to try and make my own and I found markup extensions which let you do just that, extend markup. So I decided to make a markup extension which allows me to set different xaml properties based on screen size.&lt;/p&gt;

&lt;p&gt;Here is the ResponsiveWidthProp, using similar logic we have also created one for height but for now we’ll just work with the width. It’s a pretty simple class it implements the IMarkupExtension interface, it has a public list property for Query which will hold the values and max widths we want, using the ContentProperty attribute here so we can use the elements content to set this property as well as a Default property in case we don’t have a value set for the given width. We then have a ProvideValue function that gets the current screen width then goes through the query list to find a match for the width or falls back to the default.&lt;/p&gt;

&lt;h5&gt;Markup extension&lt;/h5&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ContentProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Query&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ResponsiveWidthProp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMarkupExtension&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResponsiveSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResponsiveSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ProvideValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IServiceProvider&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serviceProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OrderBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MaxSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MaxSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MainPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ContentProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ResponsiveSet&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MaxSize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h5&gt;Usage&lt;/h5&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Image&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;HorizontalOptions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Start&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Source=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Logo&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;VerticalOptions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Start&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Image.Margin&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;xaml:ResponsiveHeightProp&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x:TypeArguments=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Thickness&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Default=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;4,24&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;xaml:ResponsiveSet&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;MaxSize=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;570&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;0,16&lt;span class=&quot;nt&quot;&gt;&amp;lt;/xaml:ResponsiveSet&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;xaml:ResponsiveSet&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;MaxSize=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1000&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;2,18&lt;span class=&quot;nt&quot;&gt;&amp;lt;/xaml:ResponsiveSet&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/xaml:ResponsiveHeightProp&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Image.Margin&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Image&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Read the docs on &lt;a href=&quot;https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/markup-extensions/creating&quot;&gt;Creating XAML Markup Extensions&lt;/a&gt; to find out more about them.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Handling image paths in Xamarin.Forms on UWP</title>
   <link href="https://dkdevelopment.net/2017/07/20/xamarin-forms-uwp-image-path//"/>
   <updated>2017-07-20T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2017/07/20/xamarin-forms-uwp-image-path/</id>
   <content type="html">&lt;p&gt;Adding a Universal Windows Platform project to an existing Xamarin.Forms Android/iOS solution is meant to &quot;just work&quot;. However when doing this myself I have found a few things that don&apos;t work as expected, one of those was images and image paths.&lt;/p&gt;

&lt;p&gt;On iOS and Android there are special folders where the platform stores it&apos;s image files, iOS has &lt;strong&gt;Resources\Images.xcassets&lt;/strong&gt; and Android has &lt;strong&gt;Resources\drawable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So on either of these 2 platforms all you need to do to add an image in xaml is something like this: &lt;strong&gt;&amp;lt;Image Source=&quot;MyIcon&quot; /&amp;gt;&lt;/strong&gt; and it would pull an image from the relevant folder for you, you don&apos;t even have to put in the file extension.&lt;/p&gt;

&lt;p&gt;I found on a UWP app this isn&apos;t the case, so I did a bit of searching and came across this on the &lt;a href=&quot;https://developer.xamarin.com/guides/xamarin-forms/user-interface/images/&quot;&gt;official Xamarin.Forms guide for images&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;blockquote&quot;&gt;
	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;iOS&lt;/strong&gt; - Place images in the  &lt;strong&gt;Resources&lt;/strong&gt; folder with  &lt;strong&gt;Build Action: BundleResource&lt;/strong&gt;. Retina versions of the image should also be supplied - two and three times the resolution with a &lt;strong&gt;@2x&lt;/strong&gt; or &lt;strong&gt;@3x&lt;/strong&gt; suffixes on the filename before the file extension (eg. &lt;strong&gt;myimage@2x.png&lt;/strong&gt;).&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Android&lt;/strong&gt; - Place images in the &lt;strong&gt;Resources/drawable&lt;/strong&gt; directory with  &lt;strong&gt;Build Action: AndroidResource&lt;/strong&gt;. High- and low-DPI versions of an image can also be supplied (in appropriately named &lt;strong&gt;Resources&lt;/strong&gt; subdirectories such as  &lt;strong&gt;drawable-ldpi&lt;/strong&gt;,  &lt;strong&gt;drawable-hdpi&lt;/strong&gt;, and &lt;strong&gt;drawable-xhdpi&lt;/strong&gt;).&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Windows Phone&lt;/strong&gt; - Place images in the application&apos;s root directory with &lt;strong&gt;Build Action: Content&lt;/strong&gt;.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Windows/UWP&lt;/strong&gt; - Place images in the application&apos;s root directory with &lt;strong&gt;Build Action: Content&lt;/strong&gt;.&lt;/li&gt;
	&lt;/ul&gt;
&lt;/div&gt;

&lt;p&gt;
	The project I am working on has just over 200 images, so putting them in the project root is ridiculous!
&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;The solution?&lt;/h3&gt;

&lt;p&gt;
	I created a custom renderer for the Image control on UWP and from there I could override the native image source and change the path of the image to one that suited me.
	This isn&apos;t a perfect solution but it&apos;s done the job so far, as long as all your images are in the same folder and have the png extension.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Collections.Generic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Linq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;DkDevelopment.UWP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Xamarin.Forms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Xamarin.Forms.Platform.UWP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Xamarin.Forms.Internals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assembly&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ExportRenderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FixedImageRenderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;DkDevelopment.UWP&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Image renderer based on The Xamarin.Forms UWP ImageRenderer&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.WinRT/ImageRenderer.cs&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Ensures images are loaded from an Images folder in the project instead of the root and they have the .png extension which is required for UWP but not iOS or Android.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FixedImageRenderer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ImageRenderer&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_disposed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_imagePrefix&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Images\\&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Dispose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;disposing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Dispose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disposing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;_disposed&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;TryUpdateSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// By default we&apos;ll just catch and log any exceptions thrown by UpdateSource so we don&apos;t bring down&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// the application; a custom renderer can override this method and handle exceptions from&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// UpdateSource differently if it wants to&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UpdateSource2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ConfigureAwait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Warning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;nameof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ImageRenderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Error loading image: {0}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IImageController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetIsLoading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;TryFixSourcePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ImageSource&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileImageSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileSource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileImageSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileSource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filePath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;StartsWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_imagePrefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;filePath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_imagePrefix&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;EndsWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;filePath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filePath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;fileSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UpdateSource2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_disposed&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Control&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetIsLoading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;ImageSource&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;TryFixSourcePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;IImageSourceHandler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Registrar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Registered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GetHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IImageSourceHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;Windows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Xaml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Media&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ImageSource&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imagesource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

                &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;imagesource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LoadImageAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OperationCanceledException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;imagesource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

                &lt;span class=&quot;c1&quot;&gt;// In the time it takes to await the imagesource, some zippy little app&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// might have disposed of this Image already.&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Control&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;Control&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imagesource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

                &lt;span class=&quot;nf&quot;&gt;RefreshImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;Control&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetIsLoading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RefreshImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IVisualElementController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;InvalidateMeasure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InvalidationTrigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RendererReady&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Get the full source here: &lt;a href=&quot;https://gist.github.com/dkarzon/fe029bc1b3e31fcb9753855437241467&quot;&gt;https://gist.github.com/dkarzon/fe029bc1b3e31fcb9753855437241467&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>What's the deal with cordova on WP</title>
   <link href="https://dkdevelopment.net/2015/04/01/cordova-on-windows-phone//"/>
   <updated>2015-04-01T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2015/04/01/cordova-on-windows-phone/</id>
   <content type="html">&lt;p&gt;
	Lately I have been talking to a few people about getting &lt;a href=&quot;http://ionicframework.com/&quot;&gt;Ionic&lt;/a&gt; (open source framework for developing hybrid mobile apps with HTML5)
	running on a Windows Phone and just talking about it has shown me that it&apos;s a little bit of a mess working with Windows solutions at the moment
    because of the convergence of Windows that has slowly been happening since Windows 8 arrived.
&lt;/p&gt;

&lt;div class=&quot;blockquote&quot;&gt;
	&lt;strong&gt;
		The aim of this post is to get those starting out with Cordova apps on Windows to better understand what&apos;s going on behind the scenes because it can greatly affect how and where the app runs.
	&lt;/strong&gt;
&lt;/div&gt;

&lt;p&gt;There are 2 ways to run Cordova on Windows Phone which have slightly different implications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Windows Phone 8.0 - This solution compiles into a Silverlight project with an embeded webview.
A few things to think about when working with this kind of project.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;This will give you greater device support (Runs on Windows Phone 8.0 and above)&lt;/li&gt;
	&lt;li&gt;Performance is not as good as below.&lt;/li&gt;
	&lt;li&gt;Less debug support within Visual Studio&lt;/li&gt;
	&lt;li&gt;Seems to be less reliable with versions of IE depending on OS versions (large difference between IE rendering between WP8.1 and WP8.1-Update1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Windows Phone 8.1 (or Universal) - This is a native javascript project as supported by the Windows Runtime (Windows 8.1 and Windows Phone 8.1)&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Less device support (only Windows Phone 8.1, apparently that is over 50% of Windows Phone users now)&lt;/li&gt;
	&lt;li&gt;Much better performance than above&lt;/li&gt;
	&lt;li&gt;100% support between Windows Store and Windows Phone&lt;/li&gt;
	&lt;li&gt;Upgrade path to Windows 10 will be a lot easier&lt;/li&gt;
	&lt;li&gt;Can debug within Visual Studio with full javascript inspection, breakpoints, DOM Explorer, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;
	Depending on how you generate your Windows Phone project with cordova determines which solution you get.
	With the current tools adding the &lt;strong&gt;wp8&lt;/strong&gt; platform will get you the silverlight project but adding the &lt;strong&gt;windows&lt;/strong&gt;
	platform will give you the native javascript solution with projects for Windows Store and Windows Phone in a universal solution.
&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Converting ANID (WP7) to ANID2 (WP8)</title>
   <link href="https://dkdevelopment.net/2014/12/25/anid-anid2-windows-phone//"/>
   <updated>2014-12-25T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2014/12/25/anid-anid2-windows-phone/</id>
   <content type="html">&lt;p&gt;
    &lt;strong&gt;Your Windows Phone 7 app uses ANID and you want to upgrade to Windows Phone 8.1 WinRT or native Javascript?&lt;/strong&gt;
    &lt;br /&gt;
    &lt;em&gt;Short answer is you can&apos;t.&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/posts/2014-12/tableflip.gif&quot; /&gt;&lt;/p&gt;

&lt;p&gt;
    &lt;strong&gt;What am I even doing here?&lt;/strong&gt;
    &lt;br /&gt;
    As the title suggests the answer is to update to either 8.0 or 8.1 sliverlight and for the love of god &lt;strong&gt;store your ids locally&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
    In Windows Phone 7 there was a property we could use called ANID &lt;code&gt;UserExtendedProperties.GetValue(&quot;ANID&quot;)&lt;/code&gt;
    this gave you a user specific id based on the logged in Microsoft account (across devices).
&lt;/p&gt;

&lt;p&gt;
    Then in Windows Phone 8 ANID was phased out and instead we were given ANID2 &lt;code&gt;UserExtendedProperties.GetValue(&quot;ANID2&quot;)&lt;/code&gt;
    which is a more specific id based on the publisher id of the application.
    This was done to improve privacy so no entity could track a user across devices and applications.
&lt;/p&gt;

&lt;p&gt;
    Now with Windows Phone 8.1 Universal apps we get the the WinRT xaml stack and native javascript apps!
    &lt;br /&gt;
    &lt;strong&gt;EVERYTHING IS AWESOME!&lt;/strong&gt;
    &lt;br /&gt;
    Wait, didn&apos;t you say you can&apos;t upgrade?
    &lt;br /&gt;
    Unfortunately moving to Universal (Either Xaml or Javascript) means you lose access to the Phone APIs such as 
    &lt;code&gt;Microsoft.Phone.Info.UserExtendedProperties&lt;/code&gt; so no access to ANID or ANID2. So we need to stay on Silverlight for now.
&lt;/p&gt;

&lt;p&gt;
    This is where I got to before cursing the world and asking myself why I didn&apos;t store the id locally.
    &lt;strong&gt;Store your ids locally!&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
    After coming to the realisation that I couldn&apos;t update to a native javascript app I started looking at how to go about the ANID to ANID2 upgrade process.
    I came across this article from the Windows blog
    &lt;a href=&quot;http://blogs.windows.com/buildingapps/2013/03/11/migrating-anids-to-windows-phone-8/&quot;&gt;http://blogs.windows.com/buildingapps/2013/03/11/migrating-anids-to-windows-phone-8/&lt;/a&gt;.
    Only to realise I was truncating the ANID because thats how the site did it where I got the code.
&lt;/p&gt;

&lt;p&gt;
    &lt;strong&gt;Don&apos;t worry if you are as well, here is how to fix it.&lt;/strong&gt;
    &lt;br /&gt;
    If you are truncating the ANID with Substring(2, 32) then all you need to do is append  &lt;code&gt;&quot;A=&quot;&lt;/code&gt;
    to the start and &lt;code&gt;&quot;&amp;amp;E=f48&amp;amp;W=3&quot;&lt;/code&gt; to the end and the converter will work for it.
&lt;/p&gt;

&lt;p&gt;
    The conversion can also be done in C# with a few lines of code:
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;//Put your publisher id here&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publisherId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Guid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;000000000-0000-0000-0000-000000000000&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anidAsBytes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Unicode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publisherAsBytes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publisherId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToByteArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;macObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;HMACSHA256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anidAsBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Take&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anidAsBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hashedBytes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;macObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ComputeHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;publisherAsBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToBase64String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hashedBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
 
 <entry>
   <title>Windows 8 sharing the right way</title>
   <link href="https://dkdevelopment.net/2014/05/08/windows8-sharing-the-right-way//"/>
   <updated>2014-05-08T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2014/05/08/windows8-sharing-the-right-way/</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;For the love of god &lt;em&gt;SetText()&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
    In Windows 8 the share charm can be a very powerful concept allowing selections of data to be easily sent between apps with a nice user experience.
    Working on the Windows 8 platform for some time I have seen a lot of apps with poorly implemented share charms and this really annoys me.
&lt;/p&gt;

&lt;p&gt;
    The first thing to do when implementing a share contract is to subscribe to the DataRequested event on the current view&apos;s DataTransferManager.
    This event will be fired when ever the share charm is invoked while you app is running.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transferManager&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataTransferManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetForCurrentView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transferManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataRequested&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OnDataRequested&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
    From this event you get access to a DataRequest object where you can set all of your properties to share to other apps.
    Below is both a bad and good example of implementing this event. I have seen too many apps using the bad example out of developer laziness or lack of understanding about what to share.

&lt;/p&gt;

&lt;p&gt;&lt;strong style=&quot;color: maroon;&quot;&gt;This is a bad example of sharing.&lt;/strong&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnDataRequested&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataTransferManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataRequestedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;My awesome app!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;I CAN HAZ FACEBOOK SHARE FEATURE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong style=&quot;color: green;&quot;&gt;This is a good example of sharing.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
    In this example we will give our share a title, description as well as a custom share test, a thumbnail and an image of the awesome emotion.
    &lt;img src=&quot;/img/posts/2014-05/test.png&quot; width=&quot;24&quot; /&gt;
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnDataRequested&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataTransferManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataRequestedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Share Tester!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;I&apos;m going to share Text, Image, Thumb, Link and StorageItems.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;//Set the text content for the share target to use&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Check this out, sharing with the Share Tester&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//NOTE: to use await you will need to call args.Request.GetDeferral() then call Complete() on the deferral&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//Get the image file you want to share&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;StorageFile&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageFile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Windows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Storage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ApplicationData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LocalFolder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetFileAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ranAccStreamRef&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RandomAccessStreamReference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateFromFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//Set an image for the share target&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetBitmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ranAccStreamRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	
	&lt;span class=&quot;c1&quot;&gt;//Set the thumbnail for the image (can set this to a different image if you have one)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Thumbnail&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ranAccStreamRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;//Some share targets prefer images as a StorageFile :S&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetStorageItems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StorageFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageFile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//Set a link to share&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://dkdevelopment.net/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3&gt;This is what you get in the share charm&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/posts/2014-05/ShareCharm.png&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;This is what we get sharing to Facebook&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/posts/2014-05/fbcharm.png&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;This is what we get sharing to Mail&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/posts/2014-05/emailcharm.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;
    If you&apos;re looking for more information about sharing checkout the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh871368.aspx&quot;&gt;MSDN Sharing content Quickstart&lt;/a&gt;
    or some of the other pages related to sharing.
    
    &lt;ul&gt;
        &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh973056.aspx&quot;&gt;Link&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh973055.aspx&quot;&gt;HTML&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh871370.aspx&quot;&gt;Image&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh871371.aspx&quot;&gt;Files&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh871375.aspx&quot;&gt;Pull operations&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh871365.aspx&quot;&gt;Async calls&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WinJS SearchBox - Suggestions, results, focus!</title>
   <link href="https://dkdevelopment.net/2013/09/03/WinJS.UI.SearchBox//"/>
   <updated>2013-09-03T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2013/09/03/WinJS.UI.SearchBox/</id>
   <content type="html">&lt;p&gt;
	In Windows 8.1 there is less focus on the search charm for apps and more on &quot;open the app and start typing&quot;.
	This is where the SearchBox control comes in, it makes it easier to add searching to your app by handling suggestions, results and focus.
	Both the XAML and WinJS stacks have this new control included but I&apos;m going to be focusing on the WinJS version of it in this post.
&lt;/p&gt;

&lt;p&gt;
	At the moment there isn&apos;t a huge amount of info on the MSDN documentation for this control (&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/dn301949.aspx&quot;&gt;WinJS.UI.SearchBox on MSDN&lt;/a&gt;).
	But it uses similar events to the search pane.
&lt;/p&gt;

&lt;p&gt;
	&lt;strong&gt;Here&apos;s a searchbox control&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/posts/SearchBox_Empty.png&quot; /&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;search&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;data-win-control=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;WinJS.UI.SearchBox&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;data-win-options=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{
	chooseSuggestionOnEnter: false,
	focusOnKeyboardInput : true,
	placeholderText: &apos;start typing anywhere&apos;,
	searchHistoryContext: &apos;search&apos;,
	searchHistoryDisabled: false,
        onsuggestionsrequested: HubPage.searchBoxSuggestionsRequested }&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div&gt;
	A few interesting properties on that:
	&lt;ul&gt;
		&lt;li&gt;
			&lt;strong&gt;focusOnKeyboardInput:&lt;/strong&gt; Automatically get focus when typing into the app window.
			This property gives the app the &quot;just start typing&quot; experience and seems to work pretty well.&lt;br /&gt;
			&lt;em&gt;&lt;u&gt;NOTE: this will also take away focus from form controls!&lt;/u&gt;&lt;/em&gt;
		&lt;/li&gt;
		&lt;li&gt;
			&lt;strong&gt;searchHistoryDisabled:&lt;/strong&gt; The SearchBox control will manage search history for you and show the previous search terms when the user focuses on the box.
		&lt;/li&gt;
		&lt;li&gt;
			&lt;strong&gt;searchHistoryContext:&lt;/strong&gt; To give you a little more control over the search history this property allows you to set a secondary key to save the results against.
			This is helpful if you use more than one SearchBox control in your app and want to keep the history separate between the two.
		&lt;/li&gt;
		&lt;li&gt;
			&lt;strong&gt;onsuggestionsrequested:&lt;/strong&gt; This is the even that fires when the user enters text in the box.
			This is where we can offer suggestions or results and the control will show a dropdown for the user.
		&lt;/li&gt;
	&lt;/ul&gt;
&lt;/div&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;searchBoxSuggestionsRequested&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;markSupportedForProcessing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//Do something with the search query to bring back suggestions&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;searchQuery&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;eventInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;queryText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;searchLanguage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;eventInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;//Populate suggestions here&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;eventInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;searchSuggestionCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendQuerySuggestion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Swat at dog&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;eventInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;searchSuggestionCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendQuerySuggestion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Stand in front of the computer screen&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;//or you can append an array of suggestions&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;eventInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;searchSuggestionCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendQuerySuggestions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;rub face on everything&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;intrigued by the shower&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;//or you can append actual result data&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//NOTE: you must handle the resultsuggestionchosen event for selection of these results&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imageUri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Windows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Foundation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ms-appx:///images/cats/section1.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imageSource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Windows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Storage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Streams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RandomAccessStreamReference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createFromUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imageUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;eventInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;searchSuggestionCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendResultSuggestion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Cat page&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;View all the cat page&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imageSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;image alt text&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div&gt;
	&lt;img style=&quot;float: left; margin-right: 24px;&quot; src=&quot;/img/posts/SearchBox_Suggestions.png&quot; /&gt;
	
	&lt;p&gt;
		We can then use the &lt;em&gt;onsuggestionsrequested&lt;/em&gt; event to add suggestions and/or results to the SearchBox.
		The above code shows the queryText and language are exposed as part of the eventInfo.
		It also allows suggestions to be added via the &lt;em&gt;searchSuggestionCollection&lt;/em&gt; property using &lt;em&gt;appendQuerySuggestion&lt;/em&gt; for adding single suggestions and
		&lt;em&gt;appendQuerySuggestions&lt;/em&gt; for adding a list.
	&lt;/p&gt;

	&lt;p&gt;
		More detailed results can also be added to the suggestions list this is dont with the &lt;em&gt;appendResultSuggestion&lt;/em&gt; function.
		This function takes a few more parameters, such as title, description, image and image alt text. But give a better result in the suggestions box (bottom item in the screenshot).
	&lt;/p&gt;

	&lt;p&gt;
		Sample code available &lt;a href=&quot;https://github.com/MarkerMetro/MarkerMetro.Talks/tree/master/WhatsNewInWindows81/CatHubSample&quot;&gt;Here on Gihub.&lt;/a&gt;
	&lt;/p&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>The Dropbox WinRT app that should have been</title>
   <link href="https://dkdevelopment.net/2013/06/16/dropbox-winrt//"/>
   <updated>2013-06-16T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2013/06/16/dropbox-winrt/</id>
   <content type="html">&lt;p&gt;
	Let me start off by saying that I am a big fan of Dropbox, I love its simplicity and their API is great to work with.
	But lately I have been thinking about switching to SkyDrive as the experience on Windows platforms are so much better.
	For me to be saying that is a pretty big deal as I use Dropbox for everything and have put so many hours into Dropbox related projects.
	However if they just put a bit more effort into the Windows RT app it would be very functional.
&lt;/p&gt;

&lt;p&gt;
	&lt;strong&gt;How do you even upload a file with the Windows RT app?&lt;/strong&gt; The short answer is: You can&apos;t.
	The long answer is: using the file picker you can save files to Dropbox.
&lt;/p&gt;

&lt;p&gt;
	Here is an example for you. I take a screenshot on my Surface RT, it automatically gets saved to the Screenshots folder under the Pictures library.
	Now opening that with the built in Photos app there is no option to save. You can Share it but not to the Dropbox app.
	From there I can open it in a photo editing app, say &quot;Enhance&quot;, make no change to the image and hit save as which will bring up the file picker where I can select Dropbox.
&lt;/p&gt;

&lt;p&gt;
	&lt;strong&gt;Have does Skydrive do this better?&lt;/strong&gt;
	Simple, they have an upload button in the app that lets you select a file and uploads it to the folder you are currently viewing.
	SkyDrive also is a Share target so from the photos app you can invoke the share charm and select Skydrive from the list.
&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;
	So I decided to dig into the Dropbox Windows Store app installed on my my PC to find it was WinJS and the code was not obfuscated or minified at all.&lt;br /&gt;
	I fired up a new project and added in all the code from the Dropbox app, sweet it works!
	Then I started to implement an upload button and about an hour later I had a working upload button using the built in file picker and the same file upload function &lt;em&gt;already in the app&lt;/em&gt;.
&lt;/p&gt;

&lt;div style=&quot;text-align: center;&quot;&gt;
	&lt;a href=&quot;/img/posts/Dropbox2_Home.png&quot;&gt;
		&lt;img src=&quot;/img/posts/Dropbox2_Home.png&quot; style=&quot;width: 48%; max-width: 800px; min-width: 310px; border: solid 4px #2D2D30;&quot; /&gt;
	&lt;/a&gt;
	&lt;a href=&quot;/img/posts/Dropbox2_Account.png&quot;&gt;
		&lt;img src=&quot;/img/posts/Dropbox2_Account.png&quot; style=&quot;width: 48%; max-width: 800px; min-width: 310px; border: solid 4px #2D2D30;&quot; /&gt;
	&lt;/a&gt;
&lt;/div&gt;

&lt;p style=&quot;margin-top: 12px;&quot;&gt;
	I added an appbar button to upload a file, easy.
	Then I couldn&apos;t see my quota info anywhere so I added it to the account flyout,
	though this would be much better suited in the top right corner with some user info (similar style to a lot of other apps, such as SkyDrive).
&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;
	&lt;strong&gt;What to do now?&lt;/strong&gt; For obvious reasons I wont be submitting this to the store nor will I be releasing the code online.
	However I would like to be able to submit it to Dropbox in the hopes of them updating their app.
&lt;/p&gt;
&lt;p&gt;
	I would also like to get your thoughts on the Dropbox app, maybe some other ways of improving it?
&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DropNet2 - async/await, WinRT and more!</title>
   <link href="https://dkdevelopment.net/2013/03/28/dropnet2//"/>
   <updated>2013-03-28T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2013/03/28/dropnet2/</id>
   <content type="html">&lt;p&gt;
	&lt;strong&gt;UPDATE:&lt;/strong&gt; DropNet2 has now been renamed to DropNetRT, check out the &lt;a href=&quot;/projects/dropnetrt/&quot;&gt;DropNetRT documentation&lt;/a&gt; for more details
&lt;/p&gt;

&lt;p&gt;DropNet has been in NuGet now for 2 years! (As of March 31st). Which means its getting old and some of the methods and technologies it was built off are out of date.&lt;/p&gt;

&lt;p&gt;
	Working on my own Windows Phone Dropbox client BoxShot I started running into some limitations of DropNet then finding that DropNet was actually being held back from by RestSharp.
	No offence to John Sheehan or any of the RestSharp contributers, they have built an excellent library which still use for numerous projects.
	However I wanted something more flexible and I wanted to use new technologies such as async/await and support for WinRT (ARM).
&lt;/p&gt;

&lt;p&gt;
	So it was time to rewrite DropNet from the ground up using not RestSharp but the new
	&lt;a href=&quot;http://blogs.msdn.com/b/bclteam/archive/2013/02/18/portable-httpclient-for-net-framework-and-windows-phone.aspx&quot;&gt;portable HTTP Client&lt;/a&gt; from Microsoft&apos;s Base Class Library which now supports Windows Phone (7.5+).
&lt;/p&gt;

&lt;p&gt;
	And here it is: &lt;a href=&quot;https://github.com/dkarzon/DropNetRT&quot;&gt;DropNet2&lt;/a&gt; (I&apos;m not very good at naming things).
	Source is available on Github including a basic Windows Phone 8 sample project (login and folder contents functionality).
&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/dkarzon/DropNetRT&quot; class=&quot;gitforked-button gitforked-forks gitforked-watchers&quot;&gt;Fork&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
	&lt;strong&gt;What different about it you say?&lt;/strong&gt; Lets have a look at the code. I kept the API pretty similar to the original.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DropNetClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;APIKEY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;APPSECRET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetUserToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;TOKEN&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SECRET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rootMetaData&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetMetaData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myFile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/MyFile.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3&gt;supported API functions&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;oauth/request_token&lt;/li&gt;
	&lt;li&gt;oauth/access_token&lt;/li&gt;
	&lt;li&gt;account/info&lt;/li&gt;
	&lt;li&gt;metadata&lt;/li&gt;
	&lt;li&gt;shares&lt;/li&gt;
	&lt;li&gt;search&lt;/li&gt;
	&lt;li&gt;media&lt;/li&gt;
	&lt;li&gt;files (GetFile and Upload)&lt;/li&gt;
	&lt;li&gt;fileops/delete&lt;/li&gt;
	&lt;li&gt;fileops/copy&lt;/li&gt;
	&lt;li&gt;fileops/move&lt;/li&gt;
	&lt;li&gt;fileops/create_folder&lt;/li&gt;
	&lt;li&gt;thumbnails&lt;/li&gt;
	&lt;li&gt;delta&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;platform support&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;.NET 4.5&lt;/li&gt;
	&lt;li&gt;.NET for Windows Store apps (WinRT)&lt;/li&gt;
	&lt;li&gt;Windows Phone 7.5 and higher&lt;/li&gt;
	&lt;li&gt;Silverlight 4 and higher&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;future plans&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;Implement remaining API functions&lt;/li&gt;
	&lt;li&gt;Progress feedback on upload and download functions&lt;/li&gt;
	&lt;li&gt;Better error handling&lt;/li&gt;
	&lt;li&gt;Support for Mono&lt;/li&gt;
	&lt;li&gt;Unit Tests&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>TFS Builds for Octopus Deploys</title>
   <link href="https://dkdevelopment.net/2012/07/15/tfs-builds-for-octopus-deploys//"/>
   <updated>2012-07-15T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2012/07/15/tfs-builds-for-octopus-deploys/</id>
   <content type="html">&lt;p&gt;I have been playing around with &lt;a href=&quot;http://octopusdeploy.com/&quot;&gt;Octopus Deploy&lt;/a&gt; lately and I have setup our TFS build server to automatically create releases and deploy to a Dev environment.&lt;/p&gt;

&lt;p&gt;Here is how you can setup a TFS build server to create NuGet packages ready for deployment through Octopus.
Building off my previous post &lt;a href=&quot;/2011/08/19/from-tfs-to-private-nuget/&quot;&gt;TFS to private NuGet.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets start with the build script:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Project&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;ToolsVersion=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;4.0&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;DefaultTargets=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Build&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Import&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Project=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;VersionMajor&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VersionMajor&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;VersionMinor&amp;gt;&lt;/span&gt;8&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VersionMinor&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;VersionPatch&amp;gt;&lt;/span&gt;1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VersionPatch&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;BuildOutputDirectory&amp;gt;&lt;/span&gt;C:\Builds\Temp\SiriuswareUtil&lt;span class=&quot;nt&quot;&gt;&amp;lt;/BuildOutputDirectory&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Target&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Build&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;MSBuild&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Projects=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;SiriuswareUtil/SiriuswareUtil.csproj&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Targets=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Build&quot;&lt;/span&gt;
			      &lt;span class=&quot;na&quot;&gt;Properties=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Configuration=Release;WebProjectOutputDir=$(BuildOutputDirectory);&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;TfsVersion&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;TfsLibraryLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0&quot;&lt;/span&gt;
		    &lt;span class=&quot;na&quot;&gt;LocalPath=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(MSBuildProjectDirectory)..\&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
			&lt;span class=&quot;nt&quot;&gt;&amp;lt;Output&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;TaskParameter=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Changeset&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;PropertyName=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ChangesetNumber&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/TfsVersion&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Copy&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;SourceFiles=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(BuildOutputDirectory)\SiriuswareUtil.nuspec&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;DestinationFolder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(BuildOutputDirectory)&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Command=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&quot;C:\NuGet\NuGet.exe&quot; pack &quot;$(BuildOutputDirectory)\SiriuswareUtil.nuspec&quot; -OutputDirectory &quot;\\grp-dev02\f$\Websites\Ardent.NuGet\Packages&quot;  -basePath &quot;$(BuildOutputDirectory)&quot; -Version &quot;$(VersionMajor).$(VersionMinor).$(VersionPatch)$(ChangesetNumber)&quot; -NoPackageAnalysis&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Command=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&quot;C:\Octopus\Octo.exe&quot; create-release --server=http://octopus.ardentleisure.com/api --project=SiriuswareUtil --deployto=Dev --apikey=YOUR_KEY_HERE&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now lets have a look at what each part does:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;VersionMajor&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VersionMajor&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;VersionMinor&amp;gt;&lt;/span&gt;8&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VersionMinor&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;VersionPatch&amp;gt;&lt;/span&gt;1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VersionPatch&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;BuildOutputDirectory&amp;gt;&lt;/span&gt;C:\Builds\Temp\SiriuswareUtil&lt;span class=&quot;nt&quot;&gt;&amp;lt;/BuildOutputDirectory&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The PropertyGroup element defines a few variables for later use.
Starting at the top there are 3 properties for the version number, these let us set the version of the package (later on we also append the TFS changeset).
The BuildOutputDirectory is a temporary path to build the project to so we can generate the NuGet package from the output.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;MSBuild&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Projects=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;SiriuswareUtil/SiriuswareUtil.csproj&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Targets=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Build&quot;&lt;/span&gt;
	&lt;span class=&quot;na&quot;&gt;Properties=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Configuration=Release;WebProjectOutputDir=$(BuildOutputDirectory);&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next we need to build the project, this part is pretty straight forward, set the path to the project file and the output directory.
This project is a web project so I&apos;m using the WebProjectOutputDir property on the build which publishs the project to the set path.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;TfsVersion&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;TfsLibraryLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0&quot;&lt;/span&gt;
	&lt;span class=&quot;na&quot;&gt;LocalPath=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(MSBuildProjectDirectory)..\&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;Output&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;TaskParameter=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Changeset&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;PropertyName=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ChangesetNumber&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TfsVersion&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we want to check what the TFS changeset is so we can append it to the package version.
For this we need the &lt;a href=&quot;https://github.com/loresoft/msbuildtasks&quot;&gt;MSBuild Community Tasks&lt;/a&gt; with the import at the top of the build script.
This function takes a few parameters such as the TFS binary location and outputs to a set variable (in this instance its &quot;ChangesetNumber&quot;).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Copy&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;SourceFiles=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(BuildOutputDirectory)\SiriuswareUtil.nuspec&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;DestinationFolder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(BuildOutputDirectory)&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The next element ensures the nuspec file is copied to the output directory, instead of having to include it as content and it getting deployed to our servers.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Command=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&quot;C:\NuGet\NuGet.exe&quot; pack &quot;$(BuildOutputDirectory)\SiriuswareUtil.nuspec&quot; -OutputDirectory &quot;\\grp-dev02\f$\Websites\Ardent.NuGet\Packages&quot;  -basePath &quot;$(BuildOutputDirectory)&quot; -Version &quot;$(VersionMajor).$(VersionMinor).$(VersionPatch)$(ChangesetNumber)&quot; -NoPackageAnalysis&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we call the NuGet command line to create the package, pointing it at our nuspec file and setting to the output to where ever out nuget server is.
This is where we also set the version of the package using our set properties and the tfs changeset number (&lt;span style=&quot;background-color: whiteSmoke; padding: 3px 5px;&quot;&gt;-Version &quot;$(VersionMajor).$(VersionMinor).$(VersionPatch)$(ChangesetNumber)&quot;&lt;/span&gt;).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Command=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&quot;C:\Octopus\Octo.exe&quot; create-release --server=http://octopus.ardentleisure.com/api --project=SiriuswareUtil --deployto=Dev --apikey=YOUR_KEY_HERE&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Lastly we want to use &lt;a href=&quot;https://github.com/dkarzon/Octopus-Tools&quot;&gt;Octopus-Tools&lt;/a&gt; octo.exe to create a release in Octopus and schedule a deploy for our Dev environment.
Octo.exe is a command line interface for the octopus server api, we just need to set a few variables for it to use such as the server address, project we want to create the release for and an API key that can be obtained through the web interface.&lt;/p&gt;

&lt;p&gt;So the process for code changes is now:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Developer checks in code to TFS&lt;/li&gt;
	&lt;li&gt;CI Build server picks up code change fires off a build of the custom script&lt;/li&gt;
	&lt;li&gt;NuGet package is created in repo&lt;/li&gt;
	&lt;li&gt;New release is created and deployed to Dev environment via Octopus&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And now I know exactly what code is running on all my servers and can easily deploy new versions.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/posts/OctopusDash.png&quot; alt=&quot;Octopus Dash&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>YeahToast -  WinJS Toast Library</title>
   <link href="https://dkdevelopment.net/2012/07/11/yeahtoast-winjs-toast-library//"/>
   <updated>2012-07-11T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2012/07/11/yeahtoast-winjs-toast-library/</id>
   <content type="html">&lt;p&gt;Windows 8 Toast notifications with WinJS isnt the easiest thing to do.
First you have to figure out what template you want, then get the XML from the template manager, then modifying the XML with the image url, title and description.
Then finally creating a toast notifier to parse the XML into a toast notification.&lt;/p&gt;

&lt;p&gt;I wanted an easier solution to add Toasts to WinJS apps, something closer to the javascript alert function: &lt;span style=&quot;background-color: whiteSmoke; padding: 3px 5px;&quot;&gt;alert(&quot;Message does here!&quot;);&lt;/span&gt;
So we started the YeahToast library, a WinJS library for easily adding toast notifications to Windows 8 applications.&lt;/p&gt;

&lt;p&gt;YeahToast can automatically determine the template to use if you dont specifically set one, it does this based on the other options you give it.
If there is an image set it will use a template with an image. If you set both text contents it will use a template with a 2 content lines.
If you just set the title it will use the template with just the title.&lt;/p&gt;

&lt;h3&gt;Basic usage:&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;YeahToast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;YEAHTOAST!&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;YeahToast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;YEAHTOAST!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;message does here&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;YeahToast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;YEAHTOAST!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;message does here&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textContent2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;message line 2&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;YeahToast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imgsrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;images/placeholder.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;This one has an image!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;something something&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3&gt;Options:&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//Windows.UI.Notifications.ToastTemplateType to define the toast template if not set YeahToast will guess based on other parameters&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;imgsrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//Image url to appear on toast&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//The toasts header text&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;textContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//Toast description line 1&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;textContent2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//Toast description line 2&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3&gt;Where to get it&lt;/h3&gt;
&lt;div class=&quot;nuget-badge&quot;&gt;
    &lt;p&gt;
		&lt;code&gt;PM&amp;gt; Install-Package YeahToast&lt;/code&gt;
	&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Or download the js file directly from Github (&lt;a href=&quot;https://github.com/Tboda/YeahToast/blob/master/lib/YeahToast.js&quot;&gt;https://github.com/Tboda/YeahToast/blob/master/lib/YeahToast.js&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;What they look like:&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/yeahtoast1.png&quot; /&gt;
&lt;br /&gt;
&lt;img src=&quot;/img/yeahtoast2.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The source for YeahToast is available on github to add the your project. There is also an example project to show basic usage.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Tboda/YeahToast&quot; class=&quot;gitforked-button gitforked-forks gitforked-watchers&quot;&gt;Fork&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Post JSON data to web services in Windows 8</title>
   <link href="https://dkdevelopment.net/2012/04/27/post-json-data-to-web-services-in-windows-8//"/>
   <updated>2012-04-27T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2012/04/27/post-json-data-to-web-services-in-windows-8/</id>
   <content type="html">&lt;p&gt;I have started working on a few metro style apps on Windows 8 using WinJS so I thought I might show some of my findings.&lt;/p&gt;

&lt;p&gt;Using the WinJS.xhr function. (&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/br229787.aspx&quot;&gt;MSDN on WinJS.xhr&lt;/a&gt;)&lt;/p&gt;

&lt;h4&gt;Lets have a look at a basic basic example: (GET)&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;WinJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;http://example.com/api/test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This function takes an options object as a parameter. The url property is the only required option for this function, this sets the url for the request.&lt;/p&gt;

&lt;h4&gt;A more advanced example: (POST)&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;WinJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;http://example.com/api/test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Content-type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;someProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;DK&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h5&gt;Looking at the example above we have set a few other options here:&lt;/h5&gt;
&lt;ul style=&quot;font-size: 16px;&quot;&gt;
    &lt;li&gt;&lt;strong&gt;type&lt;/strong&gt; - this is the HTTP method used for the request (get, post, head, etc.)&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;data&lt;/strong&gt; - this is the actual data I want to send through with the request&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;headers&lt;/strong&gt; - this lets us set specific headers on the http request (&lt;u&gt;NOTE: If your sending JSON make sure you set the content-type here!&lt;/u&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now if we wanted to add handlers for success and error we can do this using the Promise.done method (&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh701079.aspx&quot;&gt;MSDN on Promise.done&lt;/a&gt;)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;WinJS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;http://example.com/api/test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Content-type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;someProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;DK&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onSuccess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onProgress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h5&gt;There you go, thats using WinJS to post JSON data to web services.&lt;/h5&gt;
</content>
 </entry>
 
 <entry>
   <title>DroppedBoxx is now Open Source!</title>
   <link href="https://dkdevelopment.net/2012/02/21/droppedboxx-is-now-open-source//"/>
   <updated>2012-02-21T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2012/02/21/droppedboxx-is-now-open-source/</id>
   <content type="html">&lt;p&gt;Back in 2010 I started a project for uni called DroppedBoxx, it was a dropbox client for Windows Mobile 6.5. &lt;/p&gt;

&lt;p&gt;This app got me starting to develop mobile apps and sparked my interest for working with web APIs (especially Dropbox as it spawned the DropNet library). It began as a free download during its beta period to get feedback for it while I was developing it for uni and later was sold for about $1 on various stores but it is no longer available and since I no longer have a Windows Mobile 6.5 device I lost interest.&lt;/p&gt;

&lt;p&gt;No updates for almost a year :(&lt;/p&gt;

&lt;p&gt;So I have now decided to open source it!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/posts/droppedboxxrepo.png&quot; style=&quot;float: left; margin-right: 12px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I have put the source up on Github for anyone to fork, as well as the latest .cab installer. &lt;a href=&quot;https://github.com/dkarzon/DroppedBoxx&quot;&gt;https://github.com/dkarzon/DroppedBoxx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source code is actually made up of a few different components. &lt;/p&gt;

&lt;p&gt;I must give credit to &lt;a href=&quot;http://fluid.codeplex.com/&quot;&gt;Fluid .NET controls&lt;/a&gt;, DroppedBoxx has a slightly customised version of the library in it.&lt;/p&gt;

&lt;p&gt;I should also give credit to &lt;a href=&quot;http://restsharp.org/&quot;&gt;RestSharp&lt;/a&gt; for which a lot of the http request handling was based off (modified to work with .NET Compact Framework)&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/dkarzon/DroppedBoxx&quot; class=&quot;gitforked-button gitforked-forks gitforked-watchers&quot;&gt;Fork&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>JabbrPhone: It's like JabbR on your Phone</title>
   <link href="https://dkdevelopment.net/2012/01/23/jabbrphone-its-like-jabbr-on-your-phone//"/>
   <updated>2012-01-23T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2012/01/23/jabbrphone-its-like-jabbr-on-your-phone/</id>
   <content type="html">&lt;p&gt;I like development, working with new technologies and Windows Phone and over the
  past few weeks I have been working on a project that combines all of these. I call it
  JabbrPhone, its a Windows Phone client for Jabbr (the signalR based developer chat
  site).&lt;/p&gt;

&lt;p&gt;So why did I want to make a phone app for JabbR? Well simply, for fun and to try
  something new that I haven&apos;t done before (in this instance its signalR).&lt;/p&gt;

&lt;p&gt;For those who don&apos;t know what signalR is:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;&lt;em&gt;Async signaling library for .NET to help build real-time, multi-user
    interactive web applications.&lt;/em&gt;&lt;/p&gt;
  &lt;/blockquote&gt;

&lt;p&gt;It really is an awesome library. The JabbR project is also based on this and open
  sourced on Github which was great for me to get started.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2012/01/image.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/wp-content/uploads/2012/01/image_thumb.png&quot; width=&quot;263&quot; height=&quot;500&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;/wp-content/uploads/2012/01/image1.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/wp-content/uploads/2012/01/image_thumb1.png&quot; width=&quot;262&quot; height=&quot;500&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;/wp-content/uploads/2012/01/image2.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/wp-content/uploads/2012/01/image_thumb2.png&quot; width=&quot;262&quot; height=&quot;500&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;/wp-content/uploads/2012/01/image3.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/wp-content/uploads/2012/01/image_thumb3.png&quot; width=&quot;262&quot; height=&quot;500&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app isn&apos;t too far off at the moment, still a bit to do before its officially
  released. Current functionality:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;font color=&quot;#333333&quot;&gt;Login/Create user (/nick)&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font color=&quot;#333333&quot;&gt;List rooms&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font color=&quot;#333333&quot;&gt;Join a room&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font color=&quot;#333333&quot;&gt;send messages to a room (and get responses)&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font color=&quot;#333333&quot;&gt;List users in a room&lt;/font&gt;&lt;/li&gt;
  &lt;/ul&gt;

&lt;p&gt;Things left to do:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;font color=&quot;#333333&quot;&gt;Lobby functions&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font color=&quot;#333333&quot;&gt;User Actions&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font color=&quot;#333333&quot;&gt;Handle links in messages better&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font color=&quot;#333333&quot;&gt;support for private rooms&lt;/font&gt;&lt;/li&gt;
  &lt;/ul&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;The source is available on github: &lt;a href=&quot;https://github.com/dkarzon/JabbrPhone&quot;&gt;https://github.com/dkarzon/JabbrPhone&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or download the xap from here: &lt;a title=&quot;http://bit.ly/zTsCpu &quot; href=&quot;http://bit.ly/zTsCpu&quot;&gt;http://bit.ly/zTsCpu&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>abSee 'ay be see' - A/B Test library</title>
   <link href="https://dkdevelopment.net/2011/12/13/absee-ay-be-see-ab-test-library//"/>
   <updated>2011-12-13T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2011/12/13/absee-ay-be-see-ab-test-library/</id>
   <content type="html">&lt;p&gt;I have often wondered “What if” when it comes design aspects of a website.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;What if this button was green instead of blue? &lt;/li&gt;
	&lt;li&gt;What if I call it an upgrade instead of a purchase? &lt;/li&gt;
	&lt;li&gt;What if the background wasn’t as dark? &lt;/li&gt;
	&lt;li&gt;What if I make that notification flashing red instead of dark yellow? &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You get the point…&lt;/p&gt;

&lt;p&gt;So I’ve been working on an A/B testing library with the 1 goal of making it simple to insert tests into my web applications, thus abSee was born!&lt;/p&gt;

&lt;p&gt;abSee is in &lt;a href=&quot;https://nuget.org/packages/abSee&quot;&gt;NuGet&lt;/a&gt; so its pretty easy to install. (hurray!)&lt;/p&gt;

&lt;p&gt;Its usage is simple enough also:&lt;/p&gt;
&lt;p&gt;Firstly fire up an instance of the Tester, do so by calling the Start function. Or you could filter out certain users here to only show tests for them. (non-Admins etc.)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Application_BeginRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ABTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
	From there we can fire off tests to the User where ever we like by calling the Test function.
	Now to make a test we need to give it a name, this will be used to identify what we are testing in this specific instance.
	Then you give the function the different options and it will randomly select 1 for you as the output and save the result.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ABTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MyTest1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;B&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
	After running the test we then need to let the Tester know if it was successful or not so we can track conversions of the different options.
	We do this by calling the Convert function with the test name from the test we ran before. abSee will then store that result for us as converted.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;ABTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MyTest1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So now we are running tests, how do I see the results?&lt;/p&gt;

&lt;p&gt;You can get results for a given test using the GetResults function, this function returns a list of ABSeeResult which contains a few details about the test instance as well as the option that was selected and if it was converted or not.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abSee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ABTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetResults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MyTest1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;More detailed documentation is coming soon with details on implementing custom storage and user identification.&lt;/p&gt;

&lt;p&gt;Feel free to leave me some feedback about abSee or even fork it on &lt;a href=&quot;https://github.com/Tboda/abSee&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>BoxShot v2.0: Mango, Logo, Pictures hub and more</title>
   <link href="https://dkdevelopment.net/2011/11/23/boxshot-v2-0-mango-logo-pictures-hub-and-more//"/>
   <updated>2011-11-23T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2011/11/23/boxshot-v2-0-mango-logo-pictures-hub-and-more/</id>
   <content type="html">&lt;p&gt;So I got a fair bit of feedback from the old BoxShot logo and how most of my users
disliked it (some even called it offensive). Now that I&amp;acirc;&amp;euro;&amp;trade;ve had my
fun I decided to put together a serious update for the app, here is what this new
update (that I am calling v2.0) includes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;/wp-content/uploads/2011/11/Icon173.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 0px 10px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;Icon173&quot; border=&quot;0&quot; alt=&quot;Icon173&quot; align=&quot;left&quot; src=&quot;/wp-content/uploads/2011/11/Icon173_thumb.png&quot; width=&quot;177&quot; height=&quot;177&quot; /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;NEW LOGO!&lt;/h3&gt;

&lt;p&gt;As mentioned before I have changed the logo, this gives the app a more professional
look and fits in much better with the Metro UI of Windows Phone. Hope you all like
it.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;Its now Mango...&lt;/h3&gt;

&lt;p&gt;This version is build for Mango so it takes advantage of fast app switching and
general Mango goodness.&lt;/p&gt;

&lt;h3&gt;Picture Hub Integration&lt;/h3&gt;

&lt;p&gt;BoxShot now integrates into the Pictures Hub, so you can share your photos through
BoxShot to your dropbox folder.&lt;/p&gt;

&lt;h3&gt;New Dropbox API&lt;/h3&gt;

&lt;p&gt;Dropbox have recently updated their API to be more secure. For a user this pretty
much means the login process has changed, so now instead of giving the app the Email
and Password you login to the dropbox mobile site and give permission to
BoxShot.&lt;a href=&quot;/wp-content/uploads/2011/11/Tile-Copy.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 0px 0px 0px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;Tile - Copy&quot; border=&quot;0&quot; alt=&quot;Tile - Copy&quot; align=&quot;right&quot; src=&quot;/wp-content/uploads/2011/11/Tile-Copy_thumb.png&quot; width=&quot;177&quot; height=&quot;177&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Background Live Tile&lt;/h3&gt;

&lt;p&gt;The Live Tiles are now generated on the phone itself with a background agent, this
makes them much more stable.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/11/EmulatorContentsWhite.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 0px 15px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;EmulatorContentsWhite&quot; border=&quot;0&quot; alt=&quot;EmulatorContentsWhite&quot; align=&quot;left&quot; src=&quot;/wp-content/uploads/2011/11/EmulatorContentsWhite_thumb.png&quot; width=&quot;215&quot; height=&quot;390&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Referrals&lt;/h3&gt;

&lt;p&gt;BoxShot now lets you send out referral links to email or social networks so you can
get that extra free space!&lt;/p&gt;

&lt;h3&gt;Others?&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Some UI fixes (better following the metro style guide)&lt;/li&gt;

&lt;li&gt;Few bug fixes (to do with ads and the tile colour picker)&lt;/li&gt;

&lt;li&gt;Picture view now rotates and can pinch to zoom&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Download it now from the Windows Phone Marketplace!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ad-Free Version:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.windowsphone.com/en-AU/apps/1abb6e8c-d1ca-4209-a7b8-c2d657ffc9b4&quot;&gt;&lt;img src=&quot;/wp-content/uploads/2011/02/wp7_English_480x80_blue_thumb.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free&lt;/strong&gt; Version:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://windowsphone.com/s?appid=0be109c4-08be-4ac3-a96b-70ef2b0580e3&quot;&gt;&lt;img src=&quot;/wp-content/uploads/2011/02/wp7_English_480x80_blue_thumb.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div style=&quot;clear: both&quot;&gt;&lt;/div&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Future Versions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I&apos;m always open to feedback about what new features users would
like to see but heres a list of whats on the roadmap.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pin Folders to start screen (maybe files as well)&lt;/li&gt;

&lt;li&gt;Thumbnails for pictures&lt;/li&gt;

&lt;li&gt;Fix bug when uploading files with international characters&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;font color=&quot;#FF0000&quot;&gt;Update:&lt;/font&gt;&lt;/h3&gt;

&lt;p&gt;All of the above features have now been implemented in v2.2 (Thumbnails and
international characters fixed in v2.1)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>From TFS to Private NuGet</title>
   <link href="https://dkdevelopment.net/2011/08/19/from-tfs-to-private-nuget//"/>
   <updated>2011-08-19T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2011/08/19/from-tfs-to-private-nuget/</id>
   <content type="html">&lt;p&gt;Let me start by saying this: I love NuGet, its straight up awesome!&lt;/p&gt;

&lt;p&gt;This post is about how I created a TFS CI Build to create NuGet packages and push them to a private NuGet server hosted on site.&lt;/p&gt;

&lt;p&gt;
	I have been playing around with the TFS Build server, mainly for a Continuous Integration (CI)
	build on some of our projects and I wanted a way for me to be able to update a core library and
	have it propagated to all of the projects that use that library without them all needing to be in the same solution.
&lt;/p&gt;

&lt;p&gt;The answer was a private NuGet server with a CI build that automatically packaged my library.&lt;/p&gt;

&lt;p&gt;
	I started by setting up a private NuGet server, reading
	&lt;a href=&quot;http://haacked.com/archive/2011/03/31/hosting-simple-nuget-package-feed.aspx&quot;&gt;Phil Haack’s post about hosting a simple package feed&lt;/a&gt;.
	Once that was done I could start pumping out packages!
&lt;/p&gt;

&lt;p&gt;
	Now that I have my NuGet server I need to setup the build. I created an Ardent.CommonBuild.proj for my build config and tasks.
	I found its easier to manage as a separate file to the actual project file, this file has to be a .sln or .*proj file
	for the TFS Build server to be able to run it.
&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/08/image.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/wp-content/uploads/2011/08/image_thumb.png&quot; width=&quot;448&quot; height=&quot;153&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I also wanted to control the version numbers of the packages being pushed out (both manually and automatic). So I set a major and minor version property at the top.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;VersionMajor&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VersionMajor&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;VersionMinor&amp;gt;&lt;/span&gt;1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VersionMinor&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I then wanted to include the TFS Changeset number as the 3rd part of the version. So I kicked off a TfsVersion task which outputs the changeset number of a specific path (Set this to the project root to get all changes).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;TfsVersion&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;TfsLibraryLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;LocalPath=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(MSBuildProjectDirectory)&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Output&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;TaskParameter=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Changeset&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;PropertyName=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ChangesetNumber&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TfsVersion&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;From there I build the Project, normally the TFS build outputs the dlls to a binaries folder in the build output folder, but I decided to skip the nuspec file step but pointing NuGet at the project file directly. However you could create a nuspec file and point that to the built dlls, your choice. I also set the version number here for the build.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;MSBuild&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Projects=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(MSBuildProjectDirectory)\Ardent.Common\Ardent.Common.csproj&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Targets=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Build&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Properties=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Configuration=Debug;
      OutDir=$(MSBuildProjectDirectory)\Ardent.Common\Bin\Debug\;
    ApplicationVersion=$(VersionMajor).$(VersionMinor).$(ChangesetNumber)&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So now we have built our project and we have the version we want so lets create the package. Using the Exec function I then run the NuGet.exe pack command on my project file using the –Version flag to set the version of the package. I also cheated a bit here by setting the –OutputDirectory flag and pointing that to the packages folder on the NuGet server I created. This will populate the feed now with the new package.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Command=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;C:\NuGet\NuGet.exe pack $(MSBuildProjectDirectory)\Ardent.Common\Ardent.Common.csproj -Version $(VersionMajor).$(VersionMinor).$(ChangesetNumber) -OutputDirectory \\grp-dev02\f$\Websites\Ardent.NuGet\Packages&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/Exec&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The only thing left to do is create a TFS build definition under that points to my Ardent.CommonBuild.proj file in source control set the definition to CI mode. Done!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/08/image1.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/wp-content/uploads/2011/08/image_thumb1.png&quot; width=&quot;673&quot; height=&quot;308&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now for every check-in to that project in TFS I get a new package created with the updated code then NuGet handles the updates in all of my other projects.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/08/image2.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/wp-content/uploads/2011/08/image_thumb2.png&quot; width=&quot;776&quot; height=&quot;438&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Life is good…&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>BoxShot gets a live tile!</title>
   <link href="https://dkdevelopment.net/2011/08/15/boxshot-gets-a-live-tile//"/>
   <updated>2011-08-15T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2011/08/15/boxshot-gets-a-live-tile/</id>
   <content type="html">&lt;p&gt;Following the recent release of my Windows Phone 7 app &lt;a href=&quot;/2011/07/23/boxshot-its-like-dropbox-on-your-phone/&quot;&gt;BoxShot&lt;/a&gt;,
I have implemented a live tile displaying your &lt;a href=&quot;http://dropbox.com&quot;&gt;dropbox.com&lt;/a&gt; quota info.&lt;/p&gt;

&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;400&quot;&gt;
&lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;Boring old tile&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;Fancy new tile&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;Another fancy new tile&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;
			&lt;a href=&quot;/wp-content/uploads/2011/08/Default.png&quot;&gt;
				&lt;img alt=&quot;Default&quot; src=&quot;/wp-content/uploads/2011/08/Default_thumb.png&quot; /&gt;
			&lt;/a&gt;
		&lt;/td&gt;
        &lt;td&gt;
			&lt;a href=&quot;/wp-content/uploads/2011/08/Blue.png&quot;&gt;
				&lt;img alt=&quot;Default&quot; src=&quot;/wp-content/uploads/2011/08/Blue_thumb.png&quot; /&gt;
			&lt;/a&gt;
		&lt;/td&gt;
        &lt;td&gt;
			&lt;a href=&quot;/wp-content/uploads/2011/08/Pink.png&quot;&gt;
				&lt;img alt=&quot;Default&quot; src=&quot;/wp-content/uploads/2011/08/Pink_thumb.png&quot; /&gt;
			&lt;/a&gt;
		&lt;/td&gt;
    &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/08/Screen3.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 12px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;Screen3&quot; border=&quot;0&quot; alt=&quot;Screen3&quot; align=&quot;left&quot; src=&quot;/wp-content/uploads/2011/08/Screen3_thumb.png&quot; width=&quot;249&quot; height=&quot;412&quot; /&gt;&lt;/a&gt;Also, you can customise the colour of the tile from the settings
screen.&lt;/p&gt;

&lt;p&gt;Thats pretty much it for now, be sure to leave feedback for any new features you
want!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>BoxShot – Its like Dropbox on your phone…</title>
   <link href="https://dkdevelopment.net/2011/07/23/boxshot-its-like-dropbox-on-your-phone//"/>
   <updated>2011-07-23T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2011/07/23/boxshot-its-like-dropbox-on-your-phone/</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/07/BoxShotPanoramaPhone1.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;BoxShotPanoramaPhone&quot; border=&quot;0&quot; alt=&quot;BoxShotPanoramaPhone&quot; src=&quot;/wp-content/uploads/2011/07/BoxShotPanoramaPhone_thumb1.png&quot; width=&quot;700&quot; height=&quot;432&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;BoxShot is a dropbox app for Windows Phone 7.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/07/Screen1.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 0px 15px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;Screen1&quot; border=&quot;0&quot; alt=&quot;Screen1&quot; align=&quot;left&quot; src=&quot;/wp-content/uploads/2011/07/Screen1_thumb.png&quot; width=&quot;268&quot; height=&quot;444&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Open files from your Dropbox using their default apps (Office files, PDFs, etc.)&lt;/li&gt;
	&lt;li&gt;View/Edit text files within BoxShot with the built in editor&lt;/li&gt;
	&lt;li&gt;View Image files within BoxShot and save them to your library&lt;/li&gt;
	&lt;li&gt;Copy/Move files or folders within your dropbox folder&lt;/li&gt;
	&lt;li&gt;Delete files or folder from your Dropbox folder&lt;/li&gt;
	&lt;li&gt;Rename files or folders in your Dropbox folder&lt;/li&gt;
	&lt;li&gt;Email a public file link&lt;/li&gt;
	&lt;li&gt;View Account usage information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/07/Screen2.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 0px 10px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;Screen2&quot; border=&quot;0&quot; alt=&quot;Screen2&quot; align=&quot;left&quot; src=&quot;/wp-content/uploads/2011/07/Screen2_thumb.png&quot; width=&quot;268&quot; height=&quot;444&quot; /&gt;&lt;/a&gt;BoxShot also lets you add your frequently used folder to a
favourites list which are displayed on the main Panorama.&lt;/p&gt;

&lt;p&gt;Premium Version:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://windowsphone.com/s?appid=0be109c4-08be-4ac3-a96b-70ef2b0580e3&quot;&gt;&lt;img src=&quot;/wp-content/uploads/2011/02/wp7_English_480x80_blue_thumb.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Free Version:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://windowsphone.com/s?appid=0be109c4-08be-4ac3-a96b-70ef2b0580e3&quot;&gt;&lt;img src=&quot;/wp-content/uploads/2011/02/wp7_English_480x80_blue_thumb.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div style=&quot;clear: both&quot;&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>AppEvents - Do stuff when things happen (WP7)</title>
   <link href="https://dkdevelopment.net/2011/04/29/appevents-do-stuff-when-things-happen-wp7//"/>
   <updated>2011-04-29T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2011/04/29/appevents-do-stuff-when-things-happen-wp7/</id>
   <content type="html">&lt;p&gt;Ever wanted an easy way for apps to track certain events then run code based off what events the user has triggered? Well now you can with AppEvents!&lt;/p&gt;
&lt;p&gt;So AppEvents is a Windows Phone 7 library to manage events for a user across multiple sessions. In this example I will use it with CodeTrack to prompt the user to rate the app after they have added 3 repos.&lt;/p&gt;
&lt;p&gt;Lets get started, App.xaml.cs (this code can be put anywhere in the app but I felt this was better to be done at the start of the app)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;EventClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RuleSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;When&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rate-app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;el&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;addrepo&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Occurrrences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Count&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Do&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;AskToRate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now lets break that down, first we have the New() function being called, this creates the instance (and sets the Current singleton in the EventClient class). It also uses the default JsonEventStorageProvider to store the EventStore data, this can be overwritten with a type parameter on the new function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;EventClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyCustomEventStoreage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now this is where the RuleSets are added to the client using RuleSet.When() The first parameter of this function is a name of the rule. This is mainly to keep track of the rule and make sure we don’t run it twice. The second parameter is a Func&amp;lt;UserEventList, bool&amp;gt; which means we can create lamba expressions to be run against the UserEventList object, this expression tells the RuleSet when it should fire its Do Action.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RuleSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;When&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rate-app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;el&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;addrepo&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Occurrrences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Count&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Do&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;AskToRate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So where do I get it?&lt;/p&gt;

&lt;p&gt;The last part to this is firing off the events this part is very simple.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;    &lt;span class=&quot;n&quot;&gt;EventClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Fire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;addrepo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And thats pretty much it, the library then does the rest&lt;/p&gt;

&lt;p&gt;The library also allows for manual checking of events if for instance you fire an event on a page but want the RuleSet to be executed on a different page. To do this we simply add a false optional parameter to the Fire method to stop it running the RuleSets with the event. We can also manually run rules, either singly by the RuleSet name or all the rules in the list. We can also set the EventClient to not save the EventStore using the provider each time (and just have it saved later for performance).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;EventClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Fire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;addrepo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;EventClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Fire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;addrepo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;EventClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RunRule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rate-app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;EventClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RunRules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;EventClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SaveEventStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;So where do I get it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The project if on GitHub for your forking, issues and discussions.&lt;a href=&quot;https://github.com/dkarzon/AppEvents&quot; target=&quot;_blank&quot;&gt;AppEvents on Github.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows Mobile 6: Legacy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I have also made a Windows Mobile 6 version of this library but haven&apos;t actively tested it too much, if you feel like giving it a go be sure to let me know how you go.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dropbox on Windows Phone 7 with DropNet</title>
   <link href="https://dkdevelopment.net/2011/04/01/dropbox-on-windows-phone-7-with-dropnet//"/>
   <updated>2011-04-01T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2011/04/01/dropbox-on-windows-phone-7-with-dropnet/</id>
   <content type="html">&lt;p&gt;
	So I have been working on an open source Dropbox client library for a while now called DropNet.
	I have recently put this project into NuGet so its super easy to add Dropbox support to your Windows Phone 7 apps.
&lt;/p&gt;

&lt;p&gt;
	&lt;strong&gt;Update:&lt;/strong&gt; The source for this sample project is available here:
	&lt;a href=&quot;https://github.com/dkarzon/DropNet/tree/master/DropNet.Samples/DropNet.Samples.WP7&quot;&gt;https://github.com/dkarzon/DropNet/tree/master/DropNet.Samples/DropNet.Samples.WP7&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; The DropNet and DropNet-WP NuGet packages have been merged and allow for both Project Types.&lt;/p&gt;

&lt;p&gt;I’ll start with a File -&amp;gt; New Project, creating a sample Windows Phone Application.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/04/FileNew2.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;FileNew2&quot; border=&quot;0&quot; alt=&quot;FileNew2&quot; src=&quot;/wp-content/uploads/2011/04/FileNew2_thumb.png&quot; width=&quot;725&quot; height=&quot;503&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
	First thing to do is install the DropNet package, NuGet will automatically detect the type of project you are using
	and add the DropNet reference for that project type (eg. DropNet.WindowsPhone for Windows Phone 7 projects.)
&lt;/p&gt;

&lt;p&gt;
	&lt;a href=&quot;/wp-content/uploads/2011/04/DropNetNuGet.png&quot;&gt;
		&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;DropNetNuGet&quot; border=&quot;0&quot; alt=&quot;DropNetNuGet&quot; src=&quot;/wp-content/uploads/2011/04/DropNetNuGet_thumb.png&quot; width=&quot;723&quot; height=&quot;85&quot; /&gt;
	&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Ok, now we can start with the App, for starters I created a global variable for my DropNetClient instance.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;GlobalClient&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DropNetClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;API KEY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;API SECRET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now from that we will need to let the user login so my main page has a basic login form, 2 textboxes for Email and Password and a button to make it work.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Login_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//try login&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GlobalClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LoginAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;//DropNet automatically sets the result token inside the client&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;NavigationService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Navigate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/FilesPage.xaml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UriKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Relative&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;DropNets Login function automatically saves the user Token and Secret to its client instance so we dont have to set it. Then I just navigate to a new page where we will attempt to browse our Dropbox Folder.&lt;/p&gt;

&lt;p&gt;This page has a basic view model with 1 property for the folders content.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ObservableCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MetaData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ObservableCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MetaData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Contents&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_contents&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;NotifyPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Contents&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pretty easy, the page itself simply binds this collection to a listbox displaying the Name and an icon if its a folder.&lt;/p&gt;

&lt;p&gt;Ok, now to actually get the data from Dropbox… We do this by calling our DropNetClient’s GetMetaDataAsync method. This method takes a path parameter so we can tell it which folder to get the metadata for.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GlobalClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetMetaDataAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OrderBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OrderByDescending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Is_Dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2011/04/Browse1.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px&quot; border=&quot;0&quot; alt=&quot;Browse1&quot; src=&quot;/wp-content/uploads/2011/04/Browse1_thumb.png&quot; width=&quot;254&quot; height=&quot;459&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After getting the MetaData I then order it, folders first then alphabetically.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;font size=&quot;3&quot;&gt;Wait, really? Thats it?&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yep!&lt;/strong&gt; Thats my Dropbox folder.&lt;/p&gt;

&lt;p&gt;Now to make it even better we can handle the listbox’s selection change event and if the selected item was a folder we can show its contents.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ListBox_SelectionChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Windows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Controls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SelectionChangedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AddedItems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Count&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;selected&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AddedItems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MetaData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;//if its a folder browse to it&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Is_Dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Contents&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ObservableCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MetaData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;();&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GlobalClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetMetaDataAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OrderBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OrderByDescending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Is_Dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;There we go, thats the basis for a Dropbox app using DropNet, lets see what we can come up with!&lt;/p&gt;

&lt;p&gt;DropNet Implements most of the API’s functions, including :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Uploading files &lt;/li&gt;
  &lt;li&gt;Downloading files &lt;/li&gt;
  &lt;li&gt;Creating folders &lt;/li&gt;
  &lt;li&gt;Creating an account &lt;/li&gt;
  &lt;li&gt;Getting account info &lt;/li&gt;
  &lt;li&gt;Deleting files/folders &lt;/li&gt;
  &lt;li&gt;Data usage counter &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m always updating the project over at GitHub, drop by and let me know what you think or if you have any feature requests/bugs. &lt;a href=&quot;https://github.com/dkarzon/DropNet&quot; target=&quot;_blank&quot;&gt;GitHub Project.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or check out the &lt;a href=&quot;http://nuget.org/List/Packages/DropNet&quot; target=&quot;_blank&quot;&gt;NuGet Package here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
	&lt;a href=&quot;/wp-content/uploads/2011/04/Browse3.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;Browse3&quot; border=&quot;0&quot; alt=&quot;Browse3&quot; align=&quot;left&quot; src=&quot;/wp-content/uploads/2011/04/Browse3_thumb.png&quot; width=&quot;254&quot; height=&quot;459&quot; /&gt;&lt;/a&gt;
	&lt;a href=&quot;/wp-content/uploads/2011/04/Browse2.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px; padding-top: 0px&quot; title=&quot;Browse2&quot; border=&quot;0&quot; alt=&quot;Browse2&quot; align=&quot;right&quot; src=&quot;/wp-content/uploads/2011/04/Browse2_thumb.png&quot; width=&quot;254&quot; height=&quot;459&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div style=&quot;clear: both&quot;&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>DroppedBoxx v1.1 – Dropbox for Windows Mobile</title>
   <link href="https://dkdevelopment.net/2010/06/03/droppedboxx-dropbox-for-windows-mobile//"/>
   <updated>2010-06-03T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2010/06/03/droppedboxx-dropbox-for-windows-mobile/</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;Update: &lt;/strong&gt; I have now released DroppedBoxx as Open Source, the source and a downloadable cab are now available over at Github (&lt;a href=&quot;https://github.com/dkarzon/DroppedBoxx&quot;&gt;https://github.com/dkarzon/DroppedBoxx&lt;/a&gt;)&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I have been developing a Dropbox Client for Windows Mobile called DroppedBoxx and
I thought I&apos;d take some time to talk about how it works, my plans
for its future and talk about some of the new features of the latest version v1.1 which
has now been released to the &lt;a href=&quot;https://marketplace.windowsphone.com/details.aspx?appId=18925f53-bef8-43c4-adb9-f31658b133fa&quot;&gt;
Windows Phone Marketplace&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Firstly, the new features in v1.1 include: (&lt;a href=&quot;http://forum.xda-developers.com/showthread.php?t=687534&quot;&gt;Full Changelog&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two-way Syncing of selected folders&lt;/li&gt;

&lt;li&gt;Updated UI (Labeled buttons, Background Uploading, Sync Folders screen is updated
so you know when its syncing)&lt;/li&gt;

&lt;li&gt;Bug fixes for the Attach to Email and errors caused by loss of connection&lt;/li&gt;

&lt;li&gt;Added settings for camera resolution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Login:&lt;a href=&quot;/wp-content/uploads/2010/06/ScreenShot2.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; margin: 0px 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;ScreenShot2&quot; border=&quot;0&quot; alt=&quot;ScreenShot2&quot; align=&quot;right&quot; src=&quot;/wp-content/uploads/2010/06/ScreenShot2_thumb.png&quot; width=&quot;184&quot; height=&quot;244&quot; /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This screen is where the User Logs in user their dropbox account. Login button trys
to login, keyboard button shows the Windows Mobile SIP keyboard. Exit button exits the
app. Remember me saves your login details so next time you run the app your
automatically logged in.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sync Folders/Home Screen:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is pretty much the Home screen for the application. From here you can add
folders for Syncing by clicking New and browsing the phones file system and selecting a
Folder to add. The Logout button on the top right obviously logs you out returning to
the login screen.&lt;/p&gt;

&lt;p&gt;The 5 Buttons down the bottom:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Sync button starts the &amp;acirc;&amp;euro;&amp;oelig;Sync&amp;acirc;&amp;euro; process syncing
the folders in the list to your dropbox account into a folder called
&amp;acirc;&amp;euro;&amp;oelig;Droppedboxx&amp;acirc;&amp;euro; (Note: this feature is unavailable in
the Beta versions, more on that later)&lt;/li&gt;

&lt;li&gt;The Dropbox Button opens up the root folder of dropbox for you to browse.&lt;/li&gt;

&lt;li&gt;The settings button opens the settings screen where you can change app settings
(such as Clearing saved login, max file sizes and camera resolution.&lt;/li&gt;

&lt;li&gt;The Info button is to show the dropbox User info, including quota and usage but
also DroppedBoxx version information and data used by this DroppedBoxx session.&lt;/li&gt;

&lt;li&gt;The Exit button closes the app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2010/06/ScreenShot3.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; margin: 0px 0px 0px 10px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;ScreenShot3&quot; border=&quot;0&quot; alt=&quot;ScreenShot3&quot; align=&quot;right&quot; src=&quot;/wp-content/uploads/2010/06/ScreenShot3_thumb.png&quot; width=&quot;184&quot; height=&quot;244&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browse Dropbox:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where most of the functionality is, from this screen we can upload,
download, delete, etc. files from Dropbox. Starting at the top, the Back Button takes
you &amp;acirc;&amp;euro;&amp;oelig;up&amp;acirc;&amp;euro; a directory in the Dropbox file system or, if
your in the dropbox root, takes you back to the Home Screen. The Upload button lets you
browse the phones file system and select a file to upload.&lt;/p&gt;

&lt;p&gt;Here you have a list of Files and folders that are in the current folder on Dropbox
selecting a folder opens up that folder.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;The bottom button panel&lt;/u&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Camera button opens up the Windows Mobile camera application and when you
take a photo it uploads it to the folder you are currently in in the Dropbox
browser.&lt;/li&gt;

&lt;li&gt;The new folder button simply creates a new folder in the current folder, opening
up a dialog to enter the Name.&lt;/li&gt;

&lt;li&gt;The Delete folder button Deletes the current folder your in (asking for
confirmation first)&lt;/li&gt;

&lt;li&gt;The Paste button is for moving/copying files, if you have a file in the
&amp;acirc;&amp;euro;&amp;oelig;clipboard&amp;acirc;&amp;euro; pressing this button will ask if you want
to copy or move the file to this folder. (More info in file menu)&lt;/li&gt;

&lt;li&gt;The Back Button goes back to the sync folders screen (The Back button on the top
left goes up a directory or back to sync folders if your in the dropbox root)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;u&gt;&lt;a href=&quot;/wp-content/uploads/2010/06/ScreenShot41.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; margin: 5px 15px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;ScreenShot4&quot; border=&quot;0&quot; alt=&quot;ScreenShot4&quot; align=&quot;left&quot; src=&quot;/wp-content/uploads/2010/06/ScreenShot4_thumb1.png&quot; width=&quot;184&quot; height=&quot;244&quot; /&gt;&lt;/a&gt; The File Menu&lt;/u&gt;:&lt;/p&gt;

&lt;p&gt;This is the menu that comes up after selecting a dropbox file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Save Button Downloads the selected file (opening a file system browser to set the
download folder)&lt;/li&gt;

&lt;li&gt;Email button, downloads the file to a temp folder and attaches it to a New email
message in Pocket Outlook (assuming this is set up it firsts asks you to select the
account)&lt;/li&gt;

&lt;li&gt;The Copy button puts the selected file in the
&amp;acirc;&amp;euro;&amp;oelig;clipboard&amp;acirc;&amp;euro; so you can paste it somewhere else in the
dropbox file system (giving you options to Copy or Move the file)&lt;/li&gt;

&lt;li&gt;The bin button deletes the selected file (asking for confirmation first)&lt;/li&gt;

&lt;li&gt;The &amp;acirc;&amp;euro;&amp;ldquo;Menu button simply closes the file menu (to allow access
to the Folder menu again)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Settings:&lt;a href=&quot;/wp-content/uploads/2010/06/ScreenShot10.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px&quot; title=&quot;ScreenShot10&quot; border=&quot;0&quot; alt=&quot;ScreenShot10&quot; align=&quot;right&quot; src=&quot;/wp-content/uploads/2010/06/ScreenShot10_thumb.png&quot; width=&quot;184&quot; height=&quot;244&quot; /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here you can change the Settings of the application such as clearing saved login
details, setting a max filesize for sycning and setting the camera resolution for
camera uploads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Information:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This screen displays application and user info. It shows the DroppedBoxx version
number and data sent and received by the application for this session. As well as the
users dropbox quota information.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DroppedBoxx can be downloaded from the &lt;a href=&quot;https://marketplace.windowsphone.com/details.aspx?appId=18925f53-bef8-43c4-adb9-f31658b133fa&quot;&gt;
Windows Phone Marketplace&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Also you can follow the discussion about this app by going to the &lt;a href=&quot;http://bit.ly/9gqkuQ&quot;&gt;thread on XDA.&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dropbox API, RestSharp and C# Part 2: The Revenge!</title>
   <link href="https://dkdevelopment.net/2010/05/25/dropbox-api-restsharp-and-c-part-2-the-revenge//"/>
   <updated>2010-05-25T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2010/05/25/dropbox-api-restsharp-and-c-part-2-the-revenge/</id>
   <content type="html">&lt;p&gt;Following on from my previous post where I showed you how to Login and get the Account Info for a Dropbox account. Today we dive into the Box full of files. Uploading, Downloading and Deleting!&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;A lot has changed since my last post in the way of RestSharp with OAuth. OAuth is now available Out-of-the-box (this can be downloaded from &lt;a href=&quot;http://github.com/dkarzon/RestSharp&quot;&gt;Github&lt;/a&gt;). Ok, Time for some code…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Download File:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Fixed a bug in the code that only allowed for text based files to be downloaded. Using restClient.DownloadData now instead of Execute to get the response’s raw Data.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://api-content.dropbox.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//load the JsonDeserializer for all types&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ClearHandlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;JsonDeserializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;StartsWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Authenticator&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OAuthAuthenticator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_apiKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_appsecret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Resource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;{version}/files/dropbox{path}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParameterType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UrlSegment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;path&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParameterType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UrlSegment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;responseData&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DownloadData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;responseData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;u&gt;Note:&lt;/u&gt; This is assuming the user has already logged in and we have the token/secret (_userLogin).&lt;/p&gt;

&lt;p&gt;Starting from the top, we create a new Instance of the RestSharp Client with the baseUrl then set the Json Deserializer for all requests. We then set the RestClient’s Authenticator to the OAuthAuthenticator and give it our baseUrl, all our secrets and that is all we need to do for OAuth (the rest is build into RestSharp, awesome?!). Now we create the Request up, its a GET method, set the version and path of the file to download call Execute and you have just downloaded your first Dropbox API file! I then converted this to a stream so save back to a local file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delete File:&lt;/strong&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DeleteFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://api.dropbox.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//load the JsonDeserializer for all types&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ClearHandlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;JsonDeserializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;StartsWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Authenticator&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OAuthAuthenticator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_apiKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_appsecret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Resource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;{version}/fileops/delete&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParameterType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UrlSegment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;path&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;dropbox&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StatusCode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpStatusCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Delete is pretty similar to Download, only differences is the Url, the response and this time the path is sent as a parameter instead of part of the Url. The “root” parameter is for applications that only have sandbox access (they would set this to sandbox) who only get access to a “sandbox” folder on the users dropbox account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Upload File:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now this is where I had the most difficulties, many “Forbidden” messages later I finally came up with the solution!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UploadFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://api-content.dropbox.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//load the JsonDeserializer for all types&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ClearHandlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;JsonDeserializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;StartsWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//Get the file stream&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;FileStream&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FileStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;localFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileAccess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;BinaryReader&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;br&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BinaryReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numBytes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;br&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ReadBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Authenticator&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OAuthAuthenticator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_apiKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_appsecret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Resource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;{version}/files/dropbox{path}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParameterType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UrlSegment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;path&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParameterType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UrlSegment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//Need to add the &quot;file&quot; parameter with the file name&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;file&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileParameter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParameterName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;file&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StatusCode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpStatusCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ok to start with the “path” variable/parameter is the folder path (not the file).&lt;/p&gt;

&lt;p&gt;Starts off the same with the RestClient, JsonDeserializer and the OAuthAuthenticator. We also need to read the file as a byte array. Now this request is a POST so we set that in the RestRequest object then add the version and path Url parameters. We also need to add the Filename as a “file” parameter for this request as well as adding the actual file to the Request. Execute that and: {\&quot;result\&quot;: \&quot;winner!\&quot;} we just uploaded a file to dropbox!&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;This code was taken from my Dropbox open source .NET project called &lt;a href=&quot;http://github.com/dkarzon/DropNet&quot;&gt;DropNet.&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dropbox API and RestSharp for a C# developer</title>
   <link href="https://dkdevelopment.net/2010/05/18/dropbox-api-and-restsharp-for-a-c-developer//"/>
   <updated>2010-05-18T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2010/05/18/dropbox-api-and-restsharp-for-a-c-developer/</id>
   <content type="html">&lt;p&gt;
	&lt;em&gt;
		&lt;strong&gt;Update: &lt;/strong&gt; The code in this post is out dated and the version of the API is no longer supported.
		To use the Dropbox API have a look at my open source projects &lt;a href=&quot;https://dkdevelopment.net/projects/dropnetrt/&quot;&gt;DropNetRT&lt;/a&gt;
		or &lt;a href=&quot;https://dkdevelopment.net/what-im-doing/dropnet/&quot;&gt;DropNet&lt;/a&gt;.
	&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
    The Dropbox API has foiled my development of “Droppedboxx” for some time now. Mainly because the on site
    documentation is average for anyone not planning on developing for the iphone (dropbox, you used to be cool).
    Being a C# developer this was bad news for me but I decided to give it a go anyway and after a few weeks of
    failed attempts and a few emails to support about my issues I realised the API documentation on the dropbox
    website is slightly wrong.
&lt;/p&gt;
&lt;p&gt;
    So now that I have it working I thought i’d share this with my fellow .NET
    developers (and anyone else who will care to listen).
&lt;/p&gt;
&lt;p&gt;
    What you will need (What i used):
&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://restsharp.org/&quot;&gt;RestSharp&lt;/a&gt; (What would i do without you…) &lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/oauth/&quot;&gt;Oauth Library for C#&lt;/a&gt; (this one seems the easiest to use with RestSharp) &lt;/li&gt;
	&lt;li&gt;Access to the Dropbox API and an APIKey/Secret for your app &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I guess I should start with the Setup of it, I started this as a Windows Mobile application but I switched to a .NET library so I could test it easier and also use RestSharp (might open source the library if I get around to it).&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Login, this is possibly the easiest method if you have the right URL (the API documentation give you the wrong URL). We should be using “https://api.getdropbox.com/0/token” Code you say?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Got some helpful advice about using the request.Resource property with parameters instead of a string.format.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserLogin&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://api.getdropbox.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Resource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;{version}/token&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParameterType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UrlSegment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;oauth_consumer_key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_apiKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Seems pretty easy right? Most of thats RestSharp (with the JSONDeserializer), I then have the UserLogin class which is returned by this function.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserLogin&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Token&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Secret&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And now your user is logged in, you will then want to store the Users Token and Secret (storing UserLogin object would probably be better) as its used for the rest of the requests. I’ll just show you how to get the User Info as the other requests differ from the login (that is where we’ll need the Oauth stuff).&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Account/Info, I’ll start with the Response classes this time…&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AccountInfo&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Country&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Display_Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QuotaInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Quota_Info&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Uid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;QuotaInfo&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Quota&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Normal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;These are the classes for RestSharp to Deserialize the JSON to. Pretty simple, this is straight off the API Documentation site. Now for the actual request…&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AccountInfo&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Account_Info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://api.dropbox.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;OAuthBase&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oAuth&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OAuthBase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oAuth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GenerateNonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeStamp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oAuth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GenerateTimeStamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalizedUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalizedRequestParameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oAuth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GenerateSignature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{0}/{1}/account/info&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_apiKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_appsecret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeStamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalizedUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalizedRequestParameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpUtility&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;UrlEncode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RestRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Resource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{0}/account/info&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;oauth_consumer_key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_apiKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;oauth_token&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_userLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;oauth_nonce&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;oauth_timestamp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeStamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;oauth_signature_method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;HMAC-SHA1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;oauth_version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;oauth_signature&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AccountInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
    Now, this request has a different Base Url to the Login function and this uses OAuth.
    So firstly we create an instance of the RestSharp client and the OAutheBase classes.
    The OAuthBase class then handles all of the oauth parameters that we need to make the Request
    (nonce, timestamp, etc.). GenerateSignature is the main 1 that rolls up the request path and
    the tokens/secrets into a hash for extra security.
    As for the dropbox part of this, we dont need any extra parameters as we are just getting the
    logged in users Account Info. Then its just a matter of adding these parameters to the RestRequest object,
    notice the oauth_token is actually the UserLogin.Token that we got from our Login method?
&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Stay tuned for more, Tales of interest!&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I have added a &lt;a href=&quot;/2010/05/25/dropbox-api-restsharp-and-c-part-2-the-revenge/&quot;&gt;Part 2&lt;/a&gt; to this post.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Parallel vs. Async Email performance</title>
   <link href="https://dkdevelopment.net/2010/04/23/parallel-vs-async-email-performance//"/>
   <updated>2010-04-23T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2010/04/23/parallel-vs-async-email-performance/</id>
   <content type="html">&lt;p&gt;Lately i have been doing some work with sending emails and I have chosen to use some of .NET4.0’s Parallel processing and the &lt;a href=&quot;http://github.com/lukencode/FluentEmail&quot;&gt;FluentEmail&lt;/a&gt; library. &lt;/p&gt;

&lt;p&gt;I then got thinking about the Performance differences between using Parallel against Asynchronous so I decided to run some tests. Based of the &lt;a href=&quot;http://lukencode.com/2010/03/28/c-micro-performance-testing-class/&quot;&gt;C# Micro Performance Testing Class&lt;/a&gt; blog post I have written a simple app for testing this.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Firstly I created my base class for the performance tests, this will later be inherited by by different testers.&lt;/p&gt;

&lt;p&gt;Pretty basic, methods to start and finish that set the stopwatch and the finished bool…&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PerformanceTester&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TimeSpan&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TotalTime&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TimeSpan&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AverageTime&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Stopwatch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_stopwatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Iterations&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Finished&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;PerformanceTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Finished&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Iterations&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_stopwatch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Stopwatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;StartNew&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Finish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_stopwatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;AverageTime&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;TimeSpan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_stopwatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Elapsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ticks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TotalTime&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_stopwatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Elapsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Finished&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now that we have the stone to build off we can create the classes for the tests we went to perform, in this case 1 for Async and 1 for Parallel (below) these 2 classes then just override the Run method and call Finish when its done. However the async class differs slightly as it has to wait for the async callback.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ParallelEmails&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PerformanceTester&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//do stuff here&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Parallel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;For&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;//send emails&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;From&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FromAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;To&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;P&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;UsingClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SmtpClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HostAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//all done&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Finish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AsyncEmails&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PerformanceTester&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_currentIteration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//do stuff here&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;From&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FromAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;To&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Subject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;A&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;UsingClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SmtpClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HostAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SendAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emailCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;emailCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_currentIteration&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_currentIteration&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_currentIteration&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Finish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now for some results, now I know the performance will differ depending on PC hardware so I&apos;m testing this on 2 different PCs the first has a Core 2 Duo E6400 @ 2.13GHz and the 2nd has a Core 2 Quad Q6600 @ 2.4GHz.&lt;/p&gt;

&lt;p&gt;Table represents my results of the tests (in milliseconds)&lt;/p&gt;

&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;456&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td valign=&quot;top&quot; width=&quot;90&quot;&gt;&lt;strong&gt;Emails Sent&lt;/strong&gt;&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;90&quot;&gt;&lt;strong&gt;Parallel (Dual Core)&lt;/strong&gt;&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;90&quot;&gt;&lt;strong&gt;Parallel (Quad Core)&lt;/strong&gt;&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;90&quot;&gt;&lt;strong&gt;Async 
          &lt;br /&gt;(Dual Core)&lt;/strong&gt;&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;94&quot;&gt;&lt;strong&gt;Async
          &lt;br /&gt;(Quad Core)&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign=&quot;top&quot;&gt;1&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;6019&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;5716&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;83&quot;&gt;6107&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;94&quot;&gt;7039&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign=&quot;top&quot;&gt;8&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;26642&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;39571&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;83&quot;&gt;34291&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;94&quot;&gt;25638&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign=&quot;top&quot;&gt;15&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;59282&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;46897&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;83&quot;&gt;58849&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;94&quot;&gt;47730&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign=&quot;top&quot;&gt;20&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;70977&lt;/td&gt;
      &lt;td valign=&quot;top&quot;&gt;67488&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;83&quot;&gt;62120&lt;/td&gt;
      &lt;td valign=&quot;top&quot; width=&quot;94&quot;&gt;79164&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Just a note, these tests were run from the 2 PCs on the same network with the same internet connection connecting to gmails smtp server. Of course there are other factors that would affect performance of these 2 methods but this is just to get an idea of the differences.&lt;/p&gt;

&lt;p&gt;Read into that as much as you want but the main thing i got from it is parallel processing is better when you have more cores (which isn&apos;t really anything new at all). Good to see the difference in results though.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;DK out…&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fluid.NET controls for Windows Mobile 6</title>
   <link href="https://dkdevelopment.net/2010/04/20/fluid-net-controls-for-windows-mobile-6//"/>
   <updated>2010-04-20T00:00:00+00:00</updated>
   <id>https://dkdevelopment.net/2010/04/20/fluid-net-controls-for-windows-mobile-6/</id>
   <content type="html">&lt;p&gt;Lately I have been making an application for Windows mobile but I am pretty bad with design so I was looking for a control toolkit and came across the &lt;a href=&quot;http://fluid.codeplex.com/&quot;&gt;Fluid.NET controls&lt;/a&gt;, which is an open source control toolkit for Windows Mobile. Now there wasn&apos;t too much documentation on the site and it hadn&apos;t been updated for a while but they had a pretty decent looking example application which they offered the source for.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/wp-content/uploads/2010/04/Screenshot12.jpg&quot;&gt;&lt;img style=&quot;border-right-width: 0px; margin: 0px 0px 0px 10px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;Screenshot1&quot; border=&quot;0&quot; alt=&quot;Screenshot1&quot; align=&quot;right&quot; src=&quot;/wp-content/uploads/2010/04/Screenshot12.jpg&quot; width=&quot;201&quot; height=&quot;244&quot; /&gt;&lt;/a&gt;I based my project off their example, took me a while to figure out how to use some of their controls but now i have a bit more of an idea and i thought I&apos;d share it. &lt;/p&gt;

&lt;p&gt;Basically I&apos;m trying to use the Fluid.NET listbox control to display the file system (so i can select a folder).&lt;/p&gt;
&lt;p&gt;I started by using the ListBoxBase class from PasswordSafe, this class handles the general list type stuff, like changing the colour of selected list items etc. &lt;/p&gt;

&lt;p&gt;Then I created a new Fluid Template this is the class used by the ListBox to populate the items in the list. Item layout goes in the InitControl() method then the actual content of the Item (In my case its based off a DirectoryInfo object) goes in the OnBindValue() method. &lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddFolderTemplate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FluidTemplate&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FluidLabel&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FluidLabel&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secondaryLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;InitControl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;InitControl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bounds&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Rectangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;nameLabel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FluidLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;228&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;64&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Controls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;secondaryLabel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FluidLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;62&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;224&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Controls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnBindValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;folder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DirectoryInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;folder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;nameLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;secondaryLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;After I had the Template done I then created my listbox class (inheriting from the ListBoxBase) This class didnt need to do too much as most of the work is done in its base and the panel it goes in. &lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddFolderListBox&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ListBoxBase&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NotifyList&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;folders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FolderSelected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;InitControl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;InitControl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ItemHeight&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;ItemTemplate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;AddFolderTemplate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NotifyList&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Folders&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;folders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;folders&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;folders&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;DataSource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now that we’ve got the classes done, time to put them to use. I have created a panel for browsing through the file system. All we need to do here is create an instance of our Listbox control and add a list of folders to the Folders Property. &lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Controls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lsbFolders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;CurrentDir&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DirectoryInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lsbFolders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Folders&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MakeDirList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CurrentDir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetDirectories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This then loads all the folders in the devices root into the listbox. I have also added to the OnItemClick event to go deeper into the file system and a back button to go back to the parent directory. &lt;/p&gt;
</content>
 </entry>
 
 
</feed>