
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Johan de Koning</title>
	<atom:link href="http://www.johandekoning.nl/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.johandekoning.nl</link>
	<description>www.johandekoning.nl</description>
	<lastBuildDate>Thu, 05 Jan 2012 22:19:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Code Snippet: change background color of Visual Studio editor with code</title>
		<link>http://www.johandekoning.nl/index.php/2011/12/26/code-snippet-change-background-color-of-visual-studio-editor-with-code/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=code-snippet-change-background-color-of-visual-studio-editor-with-code</link>
		<comments>http://www.johandekoning.nl/index.php/2011/12/26/code-snippet-change-background-color-of-visual-studio-editor-with-code/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 12:52:47 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=651</guid>
		<description><![CDATA[When working on a project which has a trunk and branches, it happens sometimes that I am changing code at the wrong location. To make it clear that I am working on a branch I added some VB Macro to the Visual Studio IDE which changes the background color when the solution is stored in [...]]]></description>
			<content:encoded><![CDATA[<p>When working on a project which has a trunk and branches, it happens sometimes that I am changing code at the wrong location. To make it clear that I am working on a branch I added some VB Macro to the Visual Studio IDE which changes the background color when the solution is stored in a directory called &#8220;branches&#8221;. </p>
<pre class="brush: vb; title: ; notranslate">
Sub ChangeBackgroundColorForBranchProjects() Handles SolutionEvents.opened, DocumentEvents.documentopening
        Dim backgroundColor As UInt32
        backgroundColor = &amp;HFFFFFF
        If (DTE.Solution.FullName.ToLower.Contains(&quot;branches&quot;)) Then
            backgroundColor = &amp;HC0FFFF
        End If

        CType(DTE.Properties(&quot;FontsAndColors&quot;, &quot;TextEditor&quot;).Item(&quot;FontsAndColorsItems&quot;).Object, EnvDTE.FontsAndColorsItems).Item(&quot;Plain Text&quot;).Background = backgroundColor
    End Sub
</pre>
<p>You can easily add above code to Visual Studio by using the Macro IDE. I put this code within the (by default exisiting) EnvironmentEvents file part of the MyMacros project. </p>
<p>This simple code snippet checks only if the solution fullname (which includes the path) contains the word &#8220;branches&#8221;. It is of course possible to write more intelligent behaviour which looks for example to a setting file within your solution. Just use this as a starting point. Hopefully it will reduce the number of times that you are changing code within the wrong solution. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2011/12/26/code-snippet-change-background-color-of-visual-studio-editor-with-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting things done and Outlook &#8211; Keep original message attached to task or appointment</title>
		<link>http://www.johandekoning.nl/index.php/2011/07/24/getting-things-done-copy-email-to-tasklist-or-agenda-with-outlook/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=getting-things-done-copy-email-to-tasklist-or-agenda-with-outlook</link>
		<comments>http://www.johandekoning.nl/index.php/2011/07/24/getting-things-done-copy-email-to-tasklist-or-agenda-with-outlook/#comments</comments>
		<pubDate>Sun, 24 Jul 2011 10:28:24 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[David Allen]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Getting things done]]></category>
		<category><![CDATA[GTD]]></category>
		<category><![CDATA[Outlook]]></category>
		<category><![CDATA[VBA]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=633</guid>
		<description><![CDATA[To get my email, tasks and mind organized, I am trying to use the Getting Things Done method developed by David Allen (English book/Dutch book). Because I am using Outlook as &#8220;external storage system&#8221;, I read an additonal book (Iedere dag je hoofd en inbox leeg (dutch book)) about implementing GTD within Outlook. The main [...]]]></description>
			<content:encoded><![CDATA[<p>To get my email, tasks and mind organized, I am trying to use the Getting Things Done method developed by David Allen (<a href="http://www.bol.com/nl/p/engelse-boeken/getting-things-done/1001004002424081/index.html" target="_blank">English book</a>/<a href="http://www.bol.com/nl/p/nederlandse-boeken/getting-things-done/1001004005752454/index.html" target="_blank">Dutch book</a>). Because I am using Outlook as &#8220;external storage system&#8221;, I read an additonal book (<a href="http://www.bol.com/nl/p/nederlandse-boeken/elke-dag-je-hoofd-en-inbox-leeg/1001004011273995/index.html" target="_blank">Iedere dag je hoofd en inbox leeg (dutch book)</a>) about implementing GTD within Outlook.</p>
<p>The main idea of this book is that you copy emails to task lists or your agenda during the processing phase with the use of some shortcuts. With the default Copy to folder functionality of Outlook, this works quite okey with two exceptions:</p>
<ul>
<li>Attachments are not copied to a task/agenda item</li>
<li>You don&#8217;t have a reference to the original message, so you are not able to reply if you finished a task or need additional information</li>
</ul>
<p>I developed a macro with some VBA code which will create a new Outlook item (appointment or task) and attaches the orginal message to this new item. This way I can always open the original email (with attachments) and sent a reply without looking up the email in the archive folder first. </p>
<pre class="brush: vb; title: ; notranslate">
Sub CopyEmailToNewItem()

    Dim objMailItem As Outlook.mailItem

    If (ActiveExplorer.Selection.Count = 1) And (ActiveExplorer.Selection.Item(1).Class = olMail) Then
        Set objMailItem = ActiveExplorer.Selection.Item(1)
    End If

    Dim NameSpace As Outlook.NameSpace
    Set NameSpace = Outlook.GetNamespace(&quot;MAPI&quot;)

    Dim selectedFolder As Folder
    Set selectedFolder = NameSpace.PickFolder

    Const attPath As String = &quot;C:\temp\&quot;

    Set objNewItem = selectedFolder.Items.Add(selectedFolder.DefaultItemType)
    With objNewItem
        .Subject = objMailItem.Subject
        .Body = objMailItem.Body

        objMailItem.SaveAs attPath &amp; objMailItem.EntryID

        .Attachments.Add attPath &amp; objMailItem.EntryID, olEmbeddeditem, , &quot;Orginal message&quot;

        Kill (attPath &amp; objMailItem.EntryID)

        .Display
    End With
End Sub
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2011/07/24/getting-things-done-copy-email-to-tasklist-or-agenda-with-outlook/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Unittesting with WCF client dependency</title>
		<link>http://www.johandekoning.nl/index.php/2011/06/02/unittesting-with-wcf-client-dependency/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=unittesting-with-wcf-client-dependency</link>
		<comments>http://www.johandekoning.nl/index.php/2011/06/02/unittesting-with-wcf-client-dependency/#comments</comments>
		<pubDate>Thu, 02 Jun 2011 17:51:31 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Software development]]></category>
		<category><![CDATA[.Net]]></category>
		<category><![CDATA[Moq]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Unit testing]]></category>
		<category><![CDATA[wcf]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=600</guid>
		<description><![CDATA[On the Internet I found a simple calculator webservice (http://soatest.parasoft.com/calculator.wsdl). In this blogpost I will build a really simple class library which exposes the Add operation of this webservice. The purpose of this exercise is to show you how to handle this WCF dependency when unit testing the code. Calculator 1.0 &#8211; Using the generated [...]]]></description>
			<content:encoded><![CDATA[<p>On the Internet I found a simple calculator webservice (<a href="http://soatest.parasoft.com/calculator.wsdl">http://soatest.parasoft.com/calculator.wsdl</a>). In this blogpost I will build a really simple class library which exposes the Add operation of this webservice. The purpose of this exercise is to show you how to handle this WCF dependency when unit testing the code.</p>
<h3>Calculator 1.0 &#8211; Using the generated client</h3>
<p>Based on the WSDL you normally create a proxy. I prefer the use of svcutil (this makes it possible to repeat the proxy generation based on command line arguments)</p>
<p><code>svcutil /serializer:DataContractSerializer /n*:ServiceProxy /out:CalculatorProxy.cs calculator.wsdl</code></p>
<p>This generated proxy will be used in the first version of the Calculator class library</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.ServiceModel;
using ServiceProxy;

namespace CalculatorOne
{
    /// &lt;summary&gt;
    /// Implementation of a calculator which provides simple arithmetic operations
    /// &lt;/summary&gt;
    public class Calculator
    {
        /// &lt;summary&gt;
        /// Adds two numbers and returns the result
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;numberOne&quot;&gt;&lt;/param&gt;
        /// &lt;param name=&quot;numberTwo&quot;&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public float Add(float numberOne, float numberTwo)
        {
            float response = 0f;
            var calculatorClient = new CalculatorClient();

            try
            {
                response = calculatorClient.add(numberOne, numberTwo);
                calculatorClient.Close();
            }
            catch (CommunicationException)
            {
                calculatorClient.Abort();
            }
            catch (TimeoutException)
            {
                calculatorClient.Abort();
            }
            catch (Exception)
            {
                calculatorClient.Abort();
                throw;
            }

            return response;
        }
    }
}
</pre>
<p>There is quite some code for calling just a simple Add operations. Most of the code is related to exception handling to make sure that the connection is closed correctly. Don&#8217;t use the using statement to let the client proxy automatically dispose the connection, because an exception can occur within the dispose logic: <a href="http://msdn.microsoft.com/en-us/library/aa355056.aspx">http://msdn.microsoft.com/en-us/library/aa355056.aspx</a></p>
<p>Besides the huge amount of code, you are not possible to test this code without connecting to a real service. Which means that unit testing is not possible. Only integration tests against the real service are possible but you don&#8217;t want to depend on the availability of this service. When unit testing the Add operation of your library you are not interested in testing the real service. You are only interested if the dependency to the external service is called. </p>
<p>Time for version 2.0 of the Calculator class library which will inject the WCF client proxy to make mocking possible</p>
<h3>Calculator 2.0 &#8211; Inject the WCF client dependency with the use of the ChannelFactory</h3>
<p>I prefer the use of Moq (<a href="http://code.google.com/p/moq/">http://code.google.com/p/moq/</a>) as a simple mocking library. Moq only supports mocking of interfaces and virtual methods of classes. The generated proxy by svcutil does not contain virtual methods so you are unable to mock this class. Besides the generated client, there is also a channel interface (ICalculatorChannel) generated. With the WCF ChannelFactory you are able to instantiate a proxy client based on this interface.</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.ServiceModel;
using ServiceProxy;

namespace CalculatorTwo
{
    /// &lt;summary&gt;
    /// Implementation of a calculator which provides simple arithmetic operations
    /// &lt;/summary&gt;
    public class Calculator
    {
        private readonly ICalculatorChannel calculatorClient;

        public Calculator(ICalculatorChannel calculatorClient)
        {
            this.calculatorClient = calculatorClient;
        }

        /// &lt;summary&gt;
        /// Adds two numbers and returns the result
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;numberOne&quot;&gt;&lt;/param&gt;
        /// &lt;param name=&quot;numberTwo&quot;&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public float Add(float numberOne, float numberTwo)
        {
            float response = 0f;

            try
            {
                response = calculatorClient.add(numberOne, numberTwo);
                calculatorClient.Close();
            }
            catch (CommunicationException)
            {
                calculatorClient.Abort();
            }
            catch (TimeoutException)
            {
                calculatorClient.Abort();
            }
            catch (Exception)
            {
                calculatorClient.Abort();
                throw;
            }

            return response;
        }
    }
}
</pre>
<p>Now it is possible to inject a mocked client proxy when unit testing. This way you can tests if the dependency is called in the right way and you don&#8217;t depend on the availability of a real service</p>
<pre class="brush: csharp; title: ; notranslate">
[TestMethod]
public void Add_WhenClientIsMocked_ShouldMockBeCalled()
{
    //Arrange
    var client = new Mock&lt;ICalculatorChannel&gt;();
    client.Setup(c =&gt; c.add(It.IsAny&lt;float&gt;(), It.IsAny&lt;float&gt;())).Returns(42);

    var calculator = new Calculator(client.Object);

    //Act
    float response = calculator.Add(30, 12);

    //Assert
    client.Verify(c =&gt; c.add(30, 12), Times.Once());
    response.Should().BeGreaterOrEqualTo(42).And.BeLessOrEqualTo(42);
}
</pre>
<p>For assertions, I prefer the use of the FluentAssertions library (<a href="http://fluentassertions.codeplex.com/">http://fluentassertions.codeplex.com/</a>). This makes the test more readable. Above tests shows that it is possible to unit test the Add method of the Calculator class library. Still there is a lot of exception handling code and also the consumer of this class is now responsible for creating the client proxy</p>
<pre class="brush: csharp; title: ; notranslate">
[TestMethod]
public void Add_When30And12IsProvidedAsInput_Should42BeReturned()
{
    //Arrange
    var factory = new ChannelFactory&lt;ICalculatorChannel&gt;(&quot;ICalculator&quot;);
    var calculator = new Calculator(factory.CreateChannel());

    //Act
    float response = calculator.Add(30, 12);

    //Assert
    response.Should().BeGreaterOrEqualTo(42).And.BeLessOrEqualTo(42);
}
</pre>
<p>First let&#8217;s get rid of the close connection and exception handling code. Let&#8217;s move on to Calculator 3.0 </p>
<h3>Calculator 3.0 &#8211; Introducing a reusable client proxy</h3>
<p>The code for closing the client proxy connection together with the exception handling code will be used for each service operation call. By introducing a client proxy this code can be removed from the method implementation</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.ServiceModel;

namespace CalculatorThree
{
    public class ClientProxy&lt;TChannel&gt; : IClientProxy&lt;TChannel&gt; where TChannel : ICommunicationObject
    {
        private readonly TChannel innerChannel;

        public ClientProxy(TChannel innerChannel)
        {
            this.innerChannel = innerChannel;
        }

        public TResult Execute&lt;TResult&gt;(Func&lt;TChannel, TResult&gt; operation)
        {
            TResult result = default(TResult);

            try
            {
                result = operation(innerChannel);
                innerChannel.Close();
            }
            catch (CommunicationException)
            {
                innerChannel.Abort();
            }
            catch (TimeoutException)
            {
                innerChannel.Abort();
            }
            catch (Exception)
            {
                innerChannel.Abort();
                throw;
            }

            return result;
        }
    }
}
</pre>
<p>The Execute method makes use of a Func<TChannel, TResult>. Within the Add method implementation you are able to define which service operation of the proxy you want to use (together with the needed arguments). The Calculator Add method will be change to this</p>
<pre class="brush: csharp; title: ; notranslate">
using ServiceProxy;

namespace CalculatorThree
{
    /// &lt;summary&gt;
    /// Implementation of a calculator which provides simple arithmetic operations
    /// &lt;/summary&gt;
    public class Calculator
    {
        private readonly IClientProxy&lt;ICalculatorChannel&gt; clientProxy;

        public Calculator(IClientProxy&lt;ICalculatorChannel&gt; clientProxy)
        {
            this.clientProxy = clientProxy;
        }

        /// &lt;summary&gt;
        /// Adds two numbers and returns the result
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;numberOne&quot;&gt;&lt;/param&gt;
        /// &lt;param name=&quot;numberTwo&quot;&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public float Add(float numberOne, float numberTwo)
        {
            return clientProxy.Execute(c =&gt; c.add(numberOne, numberTwo));
        }
    }
}
</pre>
<p>The code is a lot cleaner (there is no connection closing and exception handling clutter anymore). Because the new client proxy can still be injected (IClientProxy) it is even still testable. For the unit test you are only interested if the dependency is called</p>
<pre class="brush: csharp; title: ; notranslate">
[TestMethod]
public void Add_WhenClientProxyIsMocked_ShouldClientProxyBeCalled()
{
    //Arrange
    var clientProxy = new Mock&lt;IClientProxy&lt;ICalculatorChannel&gt;&gt;();
    clientProxy.Setup(p =&gt; p.Execute(It.IsAny&lt;Func&lt;ICalculatorChannel, float&gt;&gt;())).Returns(42);
    var calculator = new Calculator(clientProxy.Object);

    //Act
    float response = calculator.Add(30, 12);

    //Assert

    //it is not possible / quite difficult to check with which arguments the func was called. This has to do that Moq cannot evaluate the expression.
    //therefore only the call is checked. If we want to now if the correct arguments where set, we just mock the internal proxy of the client proxy
    clientProxy.Verify(c =&gt; c.Execute(It.IsAny&lt;Func&lt;ICalculatorChannel, float&gt;&gt;()), Times.Once());
    response.Should().BeGreaterOrEqualTo(42).And.BeLessOrEqualTo(42);
}
</pre>
<p>When using the ClientProxy implementation it is still possible to mock the internal proxy. This way you are also able to check if the service operation is called with the correct arguments. This is not a unit test, but a unit integration tests: the calculator together with the client proxy are tested together</p>
<pre class="brush: csharp; title: ; notranslate">
[TestMethod]
public void Add_WhenInnerProxyOfClientProxyIsMocked_ShouldInnerProxyBeCalledWithCorrectArguments()
{
    //Arrange
    var innerProxy = new Mock&lt;ICalculatorChannel&gt;();
    innerProxy.Setup(i =&gt; i.add(It.IsAny&lt;float&gt;(), It.IsAny&lt;float&gt;())).Returns(42);

    var clientProxy = new ClientProxy&lt;ICalculatorChannel&gt;(innerProxy.Object);

    var calculator = new Calculator(clientProxy);

    //Act
    float response = calculator.Add(30, 12);

    //Assert
    innerProxy.Verify(c =&gt; c.add(30, 12), Times.Once());
    response.Should().BeGreaterOrEqualTo(42).And.BeLessOrEqualTo(42);
}
</pre>
<p>Still the consumer should create the internal proxy with the use of the ChannelFactory as shown in below integration test. To simplify this, a ProxyFactory will be introduced in Calculator version 4.0 </p>
<pre class="brush: csharp; title: ; notranslate">
[TestMethod]
public void Add_When30And12IsProvidedAsInput_Should42BeReturned()
{
    //Arrange
    var factory = new ChannelFactory&lt;ICalculatorChannel&gt;(&quot;ICalculator&quot;);
    var clientProxy = new ClientProxy&lt;ICalculatorChannel&gt;(factory.CreateChannel());

    var calculator = new Calculator(clientProxy);

    //Act
    float response = calculator.Add(30, 12);

    //Assert
    response.Should().BeGreaterOrEqualTo(42).And.BeLessOrEqualTo(42);
}
</pre>
<h3>Calculator 4.0 &#8211; Introducing a proxy factory</h3>
<p>By introducing a proxy factory, the logic for creating a proxy with the use of the ChannelFactory can be moved to a common and reusable place. </p>
<pre class="brush: csharp; title: ; notranslate">
using System.ServiceModel;

namespace CalculatorFour
{
    public class WCFProxyFactory : IProxyFactory
    {
        #region IProxyFactory Members

        public IClientProxy&lt;TChannel&gt; GetProxy&lt;TChannel&gt;(string endpointName) where TChannel : ICommunicationObject
        {
            var factory = new ChannelFactory&lt;TChannel&gt;(endpointName);
            return new ClientProxy&lt;TChannel&gt;(factory.CreateChannel());
        }

        #endregion
    }
}
</pre>
<p>The use of this proxy factory will change the calculator implementation a little bit</p>
<pre class="brush: csharp; title: ; notranslate">
using ServiceProxy;

namespace CalculatorFour
{
    /// &lt;summary&gt;
    /// Implementation of a calculator which provides simple arithmetic operations
    /// &lt;/summary&gt;
    public class Calculator
    {
        private readonly IProxyFactory proxyFactory;

        public Calculator(IProxyFactory proxyFactory)
        {
            this.proxyFactory = proxyFactory;
        }

        /// &lt;summary&gt;
        /// Adds two numbers and returns the result
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;numberOne&quot;&gt;&lt;/param&gt;
        /// &lt;param name=&quot;numberTwo&quot;&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public float Add(float numberOne, float numberTwo)
        {
            return proxyFactory.GetProxy&lt;ICalculatorChannel&gt;(&quot;ICalculator&quot;).Execute(c =&gt; c.add(numberOne, numberTwo));
        }
    }
}
</pre>
<p>Still unit, unit integration and integration testing is possible! The integration test also shows that using the Calculator class library is now more straightforward</p>
<pre class="brush: csharp; title: ; notranslate">
//Unit test
[TestMethod]
public void Add_WhenClientProxyIsMocked_ShouldClientProxyBeCalled()
{
    //Arrange
    var clientProxy = new Mock&lt;IClientProxy&lt;ICalculatorChannel&gt;&gt;();
    clientProxy.Setup(p =&gt; p.Execute(It.IsAny&lt;Func&lt;ICalculatorChannel, float&gt;&gt;())).Returns(42);

    var proxyFactory = new Mock&lt;IProxyFactory&gt;();
    proxyFactory.Setup(p =&gt; p.GetProxy&lt;ICalculatorChannel&gt;(It.IsAny&lt;string&gt;())).Returns(clientProxy.Object);

    var calculator = new Calculator(proxyFactory.Object);

    //Act
    float response = calculator.Add(30, 12);

    //Assert

    //it is not possible / quite difficult to check with which arguments the func was called. This has to do that Moq cannot evaluate the expression.
    //therefore only the call is checked. If we want to now if the correct arguments where set, we just mock the internal proxy of the client proxy
    proxyFactory.Verify(p =&gt; p.GetProxy&lt;ICalculatorChannel&gt;(&quot;ICalculator&quot;), Times.Once());
    clientProxy.Verify(c =&gt; c.Execute(It.IsAny&lt;Func&lt;ICalculatorChannel, float&gt;&gt;()), Times.Once());
    response.Should().BeGreaterOrEqualTo(42).And.BeLessOrEqualTo(42);
}

//Unit integration test
[TestMethod]
public void Add_WhenInnerProxyOfClientProxyIsMocked_ShouldInnerProxyBeCalledWithCorrectArguments()
{
    //Arrange
    var innerProxy = new Mock&lt;ICalculatorChannel&gt;();
    innerProxy.Setup(i =&gt; i.add(It.IsAny&lt;float&gt;(), It.IsAny&lt;float&gt;())).Returns(42);

    var clientProxy = new ClientProxy&lt;ICalculatorChannel&gt;(innerProxy.Object);

    var proxyFactory = new Mock&lt;IProxyFactory&gt;();
    proxyFactory.Setup(p =&gt; p.GetProxy&lt;ICalculatorChannel&gt;(It.IsAny&lt;string&gt;())).Returns(clientProxy);

    var calculator = new Calculator(proxyFactory.Object);

    //Act
    float response = calculator.Add(30, 12);

    //Assert
    innerProxy.Verify(c =&gt; c.add(30, 12), Times.Once());
    response.Should().BeGreaterOrEqualTo(42).And.BeLessOrEqualTo(42);
}

//Integration test
[TestMethod]
public void Add_When30And12IsProvidedAsInput_Should42BeReturned()
{
    //Arrange
    var factory = new WCFProxyFactory();

    var calculator = new Calculator(factory);

    //Act
    float response = calculator.Add(30, 12);

    //Assert
    response.Should().BeGreaterOrEqualTo(42).And.BeLessOrEqualTo(42);
}
</pre>
<h3>What&#8217;s next?</h3>
<p>This blog post shows that it is possible to unit tests a class/method which has a dependency with a WCF Client. By introducting the additional classes, the implementation becomes clean and testable.</p>
<p>In the final version of the calculator the proxy factory is injected by using constructor injection. It is off course possible to resolve this dependency with an IoC  (<a href="http://en.wikipedia.org/wiki/Inversion_of_control">http://en.wikipedia.org/wiki/Inversion_of_control</a>) implementation like StructureMap (<a href="http://structuremap.net/structuremap/">http://structuremap.net/structuremap/</a>) whereby the factory can be resolved without the use of constructor or property injection.</p>
<p>You can find the samples shown in the blogpost at codeplex: <a href="http://johandekoning.codeplex.com/SourceControl/changeset/view/67443#1165211">http://johandekoning.codeplex.com/SourceControl/changeset/view/67443#1165211</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2011/06/02/unittesting-with-wcf-client-dependency/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dam tot damloop 2010</title>
		<link>http://www.johandekoning.nl/index.php/2010/09/20/dam-tot-damloop-2010/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dam-tot-damloop-2010</link>
		<comments>http://www.johandekoning.nl/index.php/2010/09/20/dam-tot-damloop-2010/#comments</comments>
		<pubDate>Mon, 20 Sep 2010 21:40:59 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=588</guid>
		<description><![CDATA[19 september om 11:30 was het dan zo ver&#8230; de start van mijn eerste dam tot damloop. Het hardloopevenement waarvoor ik in maart met trainingen bij AV Zaanland was begonnen. Toen begon ik met 1 minuut hardlopen en was dan al kapot. Nu een half jaar verder heb ik er 16,1 km opzitten in 1 [...]]]></description>
			<content:encoded><![CDATA[<p>19 september om 11:30 was het dan zo ver&#8230; de start van mijn eerste dam tot damloop. Het hardloopevenement waarvoor ik in maart met trainingen bij AV Zaanland was begonnen. Toen begon ik met 1 minuut hardlopen en was dan al kapot. Nu een half jaar verder heb ik er 16,1 km opzitten in 1 uur 39 minuten en 33 seconden.</p>
<p style="text-align: center;"><a href="http://www.johandekoning.nl/wp-content/uploads/2010/09/dtd10-23368.jpg"><img class="size-medium wp-image-589 aligncenter" title="Dam tot damloop 2010" src="http://www.johandekoning.nl/wp-content/uploads/2010/09/dtd10-23368-333x500.jpg" alt="" width="333" height="500" /></a></p>
<p>Het meedoen aan de dam tot damloop is erg gaaf. Ik zelf vond het door te ijtunnel lopen toch wel een hoogtepunt van het parcours omdat ik daar enkel met de bus of auto doorheen ben gereden. Maar ook de hoeveelheid mensen langs de weg maakt een enorme indruk. Ik ga de training bij AV Zaanland doorzetten dus wellicht volgend jaar weer&#8230;</p>
<p><a href="http://evenementen.uitslagen.nl/2010/damloop/details.php?s=7552" target="_blank">Uitslag </a><br />
<a href="http://www.runnersweb.nl/runnerstv?e=DT1010EM&amp;n=Johan%20de%20Koning&amp;r=7552&amp;ct_s1=11:31:42&amp;ct_s2=12:02:08&amp;nt_s2=00:30:26&amp;ct_s3=12:33:15&amp;nt_s3=01:01:33&amp;ct_s4=12:52:07&amp;nt_s4=01:20:26&amp;ct_s5=13:04:39&amp;nt_s5=01:32:58&amp;ct_f=13:11:15&amp;nt_f=01:39:33&amp;l=NL" target="_blank">Video&#8217;s</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2010/09/20/dam-tot-damloop-2010/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WCF Data Contract Schema validation with Schematron</title>
		<link>http://www.johandekoning.nl/index.php/2010/05/18/wcf-data-contract-schema-validation-with-schematron/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wcf-data-contract-schema-validation-with-schematron</link>
		<comments>http://www.johandekoning.nl/index.php/2010/05/18/wcf-data-contract-schema-validation-with-schematron/#comments</comments>
		<pubDate>Mon, 17 May 2010 22:20:44 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=570</guid>
		<description><![CDATA[WCF is mostly used within a code first implementation. The data contract and service operations are implemented as methods within a class which are decorated with attributes (like [DataContract] and [DataMember]). With these attribute the types define that they are serializable with a serializer such as the DataContractSerializer. The DataContractSerializer is an optimized serializer which [...]]]></description>
			<content:encoded><![CDATA[<p>WCF is mostly used within a code first implementation. The data contract and service operations are implemented as methods within a class which are decorated with attributes (like [DataContract] and [DataMember]). With these attribute the types define that they are serializable with a serializer such as the DataContractSerializer. The DataContractSerializer is an optimized serializer which is faster than the XmlSerializer (<a href="http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/">http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/</a>). A consequent of this optimalization is that only a subset of the XML Schema (XSD) is supported: <a href="http://msdn.microsoft.com/en-us/library/ms733112.aspx">http://msdn.microsoft.com/en-us/library/ms733112.aspx</a></p>
<p>When working with existing systems, it is most times not possible to use the code first approach for the definition of the data contract. XSD and WSDL are exposed by existing services which makes client proxy and data contract code generation possible with the use of <em>svcutil</em>. By default <em>svcutil </em>tries to use to DataContractSerializer and falls back to the XmlSerializer when usage of the DataContractSerializer is not possible (it is possible to force the use of the data contract serializer by supplying the /serializer:datacontractserializer argument, which not falls back to the XmlSerializer but returns an error when it is not able to generate the code).</p>
<p>Within a situation that WSDL and XSD are leading but changes can be made to support the DataContractSerializer, it can be time consuming to update those service definitions files. The svcutil tool gives limited feedback when it fails to use the DataContractSerializer and it does not give you a clear overview of the issues that should be solved to make it compliant to this serializer.</p>
<h2>Schematron</h2>
<p>Schematron is a rule-based validation language for making assertions about the presence or absence of patterns in XML trees. It is a structural schema language expressed in XML using a small number of elements and XPath. (<a href="http://en.wikipedia.org/wiki/Schematron">http://en.wikipedia.org/wiki/Schematron</a>). With the use of a Schematron rule set file, additional conditions can be defined for the data contract schema definition.</p>
<p>Schematron (http://www.schematron.com/) is an ISO standard (<a href="http://standards.iso.org/ittf/PubliclyAvailableStandards/c040833_ISO_IEC_19757-3_2006(E).zip">http://standards.iso.org/ittf/PubliclyAvailableStandards/c040833_ISO_IEC_19757-3_2006(E).zip</a>) and makes it possible to define constraints which cannot be expressed/defined within a XML Schema (XSD). It is possible to define rules which take related elements into account. Within a Schematron rule set file, rules are made by specifying assertions. An example of a rule</p>
<pre class="brush: xml; title: ; notranslate">
&lt;sch:pattern id=&quot;schema-element-attribute-error&quot;&gt;
	&lt;sch:rule context=&quot;xsd:schema/xsd:element&quot;&gt;
		&lt;sch:assert test=&quot;@nillable = 'true'&quot;&gt;Must be true for associated GEDs.&lt;/sch:assert&gt;
	&lt;/sch:rule&gt;
&lt;/sch:pattern&gt;
</pre>
<p>Above rules makes sure that global element declarations (xsd:element directly defined within xsd:schema) should have the nillable=&#8221;true&#8221; attribute.</p>
<p>Besides &lt;assert&gt; there is also a &lt;report&gt; assertion. When the Schematron rule set is applied on an XML file, &lt;assert&gt; is logged when the condition fails (positive assertions). On the other side &lt;report&gt; is logged (within the output file) when the condition is met (negative assertions). For example when above rule fails on the supplied data contract schema definition, the output file (SVRL, Schematron Validator Report Language) will contain:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;svrl:active-pattern id=&quot;schema-element-attribute-error&quot; name=&quot;schema-element-attribute-error&quot;/&gt;
	&lt;svrl:fired-rule context=&quot;xsd:schema/xsd:element&quot;/&gt;
	&lt;svrl:failed-assert test=&quot;@nillable = 'true'&quot; location=&quot;/*[local-name()='schema' and namespace-uri()='http://www.w3.org/2001/XMLSchema']/*[local-name()='element' and namespace-uri()='http://www.w3.org/2001/XMLSchema'][1]&quot;&gt;
		&lt;svrl:text&gt;Must be true for associated GEDs.&lt;/svrl:text&gt;
	&lt;/svrl:failed-assert&gt;
&lt;svrl:fired-rule context=&quot;xsd:schema/xsd:element&quot;/&gt;
</pre>
<p>whereby the location of the element causing this failure is part of the result message (location attribute).</p>
<h2>Applying an schematron ruleset</h2>
<p>A Schematron rule set file is converted to an XSLT file which will be applied on the XML file on which the assertions should be executed. This is a pipelined process whereby the Schematron file is tranformed by different XSL files (and an XSLT engine) as shown in the diagram below</p>
<p><a href="http://www.johandekoning.nl/wp-content/uploads/2010/05/Flow.jpg"><img class="aligncenter size-full wp-image-573" title="Schematron Flow" src="http://www.johandekoning.nl/wp-content/uploads/2010/05/Flow.jpg" alt="" width="467" height="567" /></a></p>
<p>When using the basic elements of Schematron, only one transformation is needed before it can be applied on a file which should be validated. I used the Schematron XSLT1 implementation (<a href="http://www.schematron.com/tmp/iso-schematron-xslt1.zip">http://www.schematron.com/tmp/iso-schematron-xslt1.zip</a>) together with the free AltovaXML XSLT Engine (<a href="http://www.altova.com/altovaxml.html">http://www.altova.com/altovaxml.html</a>)</p>
<pre>AltovaXML /xslt1 iso_svrl_for_xslt1.xsl /in datacontract.sch /out datacontract.xsl
AltovaXML /xslt1 datacontract.xsl /in &lt;xsd schema which should be checked&gt;  /out result.svrl</pre>
<h2>Data Contract Validator</h2>
<p>With the use of Schematron it is possible to make a data contract serializer validator, which gives you a quick overview of issues to make use of the Data Contract Serializer possible. I developed a first implementation of this rule set based on the Data Contract Schema Reference (<a href="http://msdn.microsoft.com/en-us/library/ms733112.aspx">http://msdn.microsoft.com/en-us/library/ms733112.aspx</a>). Not all rules are implemented yet.</p>
<p>When validating a data contract XSD there are errors (a Global Element Declarations should have @nillable=&#8217;true&#8217;) and warnings (attribute @id is ignored). To distinguish between both validation types I used for the errors, and for warnings/verbose information.</p>
<p>You can download the Data Contract Schematron Rule set at <a href="http://johandekoning.codeplex.com/SourceControl/changeset/view/48265#831939">http://johandekoning.codeplex.com/SourceControl/changeset/view/48265#831939</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2010/05/18/wcf-data-contract-schema-validation-with-schematron/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Turing machine implementation with WF4 and FlowChart</title>
		<link>http://www.johandekoning.nl/index.php/2010/04/07/turing-machine-implementation-with-wf4-and-flowchart/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=turing-machine-implementation-with-wf4-and-flowchart</link>
		<comments>http://www.johandekoning.nl/index.php/2010/04/07/turing-machine-implementation-with-wf4-and-flowchart/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 21:16:24 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.Net]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[FlowChart]]></category>
		<category><![CDATA[WF4]]></category>
		<category><![CDATA[XAML]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=532</guid>
		<description><![CDATA[A couple of days ago I received a tweet about a real hardware implementation of the Turing Machine (http://www.aturingmachine.com/). Impressed about this implementation, I was thinking about how to implement a simple Turing Machine counting program with the use of Workflow Foundation 4. And that&#8217;s where the story starts about my first experience with WF4. [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of days ago I received a tweet about a real hardware implementation of the Turing Machine (<a href="http://www.aturingmachine.com/">http://www.aturingmachine.com/</a>). Impressed about this implementation, I was thinking about how to implement a simple Turing Machine counting program with the use of Workflow Foundation 4. And that&#8217;s where the story starts about my first experience with WF4.</p>
<p><object width="640" height="385" class="aligncenter"><param name="movie" value="http://www.youtube.com/v/E3keLeMwfHY&#038;rel=0&#038;color1=0xb1b1b1&#038;color2=0xcfcfcf&#038;hl=en_US&#038;feature=player_embedded&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowScriptAccess" value="always"></param><embed class="aligncenter" src="http://www.youtube.com/v/E3keLeMwfHY&#038;rel=0&#038;color1=0xb1b1b1&#038;color2=0xcfcfcf&#038;hl=en_US&#038;feature=player_embedded&#038;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="385"></embed></object></p>
<h3>Turing machine definition</h3>
<p>At Wikipedia a definition of the Turing machine can be found: <a href="http://en.wikipedia.org/wiki/Turing_machine">http://en.wikipedia.org/wiki/Turing_machine</a>. To keep it short, a Turing machine consists of two parts</p>
<ul>
<li>A tape of unlimited length which is separated in cells</li>
<li>A machine that can read/write on the tape</li>
</ul>
<p>The machine is a finite state machine. The machine is in one state and with the use of a set of rules the machine can transfer to a different state. A rule contains the following parts</p>
<ul>
<li>current state</li>
<li>symbol read</li>
<li>next state</li>
<li>symbol to write</li>
<li>move direction</li>
</ul>
<p>The following rule <em>[state: 0, read: blank, new state: 1, write: blank, move: left]</em> will be executed by the machine when the current state is 0 and the value of the cell on the tape is blank. When the rule is executed, the machine will transfer to state 1, keeps the cell blank and will move the tape one cell to the left. A next rule for state 1 will be executed based on the new cell value read on the new tape position. </p>
<p>The machine part will be written with the use of a workflow diagram. This diagram will contain the different states and rule actions.</p>
<h3>Counting rules</h3>
<p>The rules for making counting possible (as taken from the aturingmachine.com website)</p>
<p>[state: 0, read: 1, new state: 0 write: 1, move: right]<br />
[state: 0, read: 0, new state: 0, write: 0, move: right]<br />
[state: 0, read: blank, new state: 1, write: blank, move: left]</p>
<p>[state: 1, read: 0, new state: 0, write: 0, move: right]<br />
[state: 1, read: 1, new state: 1, write: 0, move: left]<br />
[state: 1, read: blank, new state: 0, write: 1, move: right]</p>
<h3>Tape implementation</h3>
<p>The tape is a collection of cells which has an unlimited length. New cells can be added at the start or end of the written tape part. To support this functionality, an implementation is made based on a List collection making it possible to not only add new values at the end of the tape but also at the beginning.</p>
<pre class="brush: csharp; title: ; notranslate">
public class Tape : ITape
    {
        public int Position { get; private set; }
        public int Length { get { return _internalCollection.Count; } }

        private List&lt;int?&gt; _internalCollection;

        public Tape()
        {
            Position = 0;
            _internalCollection = new List&lt;int?&gt;(){null};
        }

        public int? ReadCell()
        {
            return _internalCollection[Position];
        }

        public void WriteCell(int? cellValue)
        {
            _internalCollection[Position] = cellValue;
        }

        public void MoveCell(MoveDirection direction)
        {
            switch(direction){
                case MoveDirection.Left:
                    if (Position == 0)
                    {
                        _internalCollection.Insert(0, null);
                    }
                    else
                    {
                        Position--;
                    }
                    break;
                case MoveDirection.Right:
                    Position++;
                    if (Position == _internalCollection.Count)
                    {
                        _internalCollection.Add(null);
                    }
                    break;
            }
        }

        public override string ToString()
        {
            StringBuilder tapeValue = new StringBuilder(&quot;[&quot;);
            foreach (var cell in _internalCollection)
            {
                if (cell == null) { tapeValue.Append(&quot; &quot;); } else { tapeValue.Append(cell.ToString()); }
            }
            tapeValue.Append(&quot;] &quot;);
            return tapeValue.ToString();
        }
    }
</pre>
<h3>Flowchart</h3>
<p>The state workflow of Workflow Foundation 3 is not part of version 4. The alternative given is the flowchart. With the flow chart certain types of state machine workflows can be implemented (but not all of them). A flowchart is powerful and simple to use, making it possible to loop back to previous executed activities. This is very useful for moving between the different states.</p>
<p>Together with the Flowchart, two activities are introducted: FlowDecision and FlowSwitch. A FlowDecision can be seen as an if condition while the FlowSwitch is like a switch statement in code. The FlowSwitch will be the central decision node for each state within the turing machine counting implementation</p>
<h3>Workflow implementation with standard activities</h3>
<p>A console workflow application is used for this implementation. An instance of the Tape is set as variable on the FlowChart.</p>
<p>The counting program can be developed with the use of the standard activities provided by WF4. The following activities are used</p>
<ul>
<li>FlowSwitch: based on the cell value an execution path is chosen</li>
<li>InvokeMethod: used for executing the WriteCell and MoveCell methods</li>
<li>WriteLine: write the value of all cell values to the console.</li>
<li>Delay: this activiity is optional. Some delay to make output more readable during execution</li>
</ul>
<p>The default path of the FlowSwitch activity is used for supporting the blank values. This is because of the fact that FlowSwitch works with string values, making it impossible to define a path for a null value.</p>
<p><a href="http://www.johandekoning.nl/wp-content/uploads/2010/04/CountingWorkflow.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2010/04/CountingWorkflow-379x499.jpg" alt="" title="Counting workflow" width="379" height="499" class="aligncenter size-medium wp-image-542" /></a></p>
<h3>Custom activities</h3>
<p>The InvokeMethod activity is a generic activity to make execution of a method possible. It takes some time to configure each activity. The method parameters (for example the cell value which should be written) are implemented as a Parameter collection, which are not directly visible from the property editor within Visual Studio. To simplify/fasten this assignment process, custom activities will be developed to support the specific methods on the Tape instance. </p>
<p>Custom code activities are based on the CodeActivity or NativeActivity class. The CodeActivity is for creating simple synchronous custom activities. This model is suitable for the custom activities needed by the turing machine workflow. When you want to use all of the functionality exposed by the WF4 runtime, you should use the NativeActivity base class. </p>
<p>Two custom activities are developed</p>
<ul>
<li>MoveCell activity: for moving the position on the tape one cell. The Direction property holds the move direction</li>
<li>WriteCell activity: for writing a cell value on the current position. The CellValue property holds the value which should be written</li>
</ul>
<pre class="brush: csharp; title: ; notranslate">
namespace TuringMachine.Activities
{
    [Designer(typeof(MoveCellDesigner))]
    public sealed class MoveCell : CodeActivity
    {
        [RequiredArgument()]
        public InArgument&lt;ITape&gt; Tape { get; set; }

        public MoveDirection Direction { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            var tape = context.GetValue(Tape);
            tape.MoveCell(Direction);
        }
    }
}
</pre>
<pre class="brush: csharp; title: ; notranslate">
namespace TuringMachine.Activities
{
    [Designer(typeof(WriteCellDesigner))]
    public sealed class WriteCell : CodeActivity
    {
        [RequiredArgument()]
        public InArgument&lt;Nullable&lt;int&gt;&gt; CellValue { get; set; }

        [RequiredArgument()]
        public InArgument&lt;ITape&gt; Tape { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            var tape = context.GetValue(Tape);
            var cellValue = context.GetValue(CellValue);

            tape.WriteCell(cellValue);
        }
    }
}
</pre>
<p>The InArgument type used for the properties can hold (besides a value like a normal property) an expression. Those expression are defined using the VB.Net language (so null should be defined as Nothing)</p>
<p>The custom activities are added to the Workflow Toolbox making it possible to drag them into the workflow. You can change the property values from within the Property editor</p>
<p><a href="http://www.johandekoning.nl/wp-content/uploads/2010/04/PropertyEditorVisualStudio.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2010/04/PropertyEditorVisualStudio-499x263.jpg" alt="" title="PropertyEditorVisualStudio" width="499" height="263" class="aligncenter size-medium wp-image-547" /></a></p>
<h3>Custom design</h3>
<p>When viewing the diagram, it is still not directly clear which values are written and to which direction the position on the tape is moved. WF4 makes it possible to assign a design to a custom activity. The design of the activity is developed with XAML. Assignment is done with the use of the Designer attribute (as shown in the code above)</p>
<p>The XAML used for the MoveCell activity makes it possible to directly select the move direction from within the diagram</p>
<p><a href="http://www.johandekoning.nl/wp-content/uploads/2010/04/ScreenShot004.png"><img src="http://www.johandekoning.nl/wp-content/uploads/2010/04/ScreenShot004.png" alt="" title="Move Cell Activity" width="236" height="86" class="aligncenter size-full wp-image-552" /></a></p>
<pre class="brush: xml; title: ; notranslate">
&lt;sap:ActivityDesigner x:Class=&quot;TuringMachine.Activities.Designer.MoveCellDesigner&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:sap=&quot;clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation&quot;
    xmlns:sapv=&quot;clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation&quot;
    xmlns:sys=&quot;clr-namespace:System;assembly=mscorlib&quot;
    xmlns:tm=&quot;clr-namespace:TuringMachine.Classes;assembly=TuringMachine.Classes&quot;&gt;
    &lt;sap:ActivityDesigner.Resources&gt;
        &lt;ObjectDataProvider MethodName=&quot;GetValues&quot; ObjectType=&quot;{x:Type sys:Enum}&quot; x:Key=&quot;MoveDirectionValues&quot;&gt;
            &lt;ObjectDataProvider.MethodParameters&gt;
                &lt;x:TypeExtension TypeName=&quot;tm:MoveDirection&quot;/&gt;
            &lt;/ObjectDataProvider.MethodParameters&gt;
        &lt;/ObjectDataProvider&gt;
    &lt;/sap:ActivityDesigner.Resources&gt;
    &lt;Grid&gt;
        &lt;Grid.ColumnDefinitions&gt;
            &lt;ColumnDefinition Width=&quot;auto&quot;/&gt;
            &lt;ColumnDefinition Width=&quot;*&quot;/&gt;
        &lt;/Grid.ColumnDefinitions&gt;
        &lt;Grid.RowDefinitions&gt;
            &lt;RowDefinition Height=&quot;*&quot;/&gt;
        &lt;/Grid.RowDefinitions&gt;
        &lt;TextBlock VerticalAlignment=&quot;Center&quot;&gt;Direction:&lt;/TextBlock&gt;
        &lt;ComboBox Grid.Column=&quot;1&quot; ItemsSource=&quot;{Binding Source={StaticResource MoveDirectionValues}}&quot; SelectedValue=&quot;{Binding ModelItem.Direction, Mode=TwoWay}&quot;&gt;&lt;/ComboBox&gt;
    &lt;/Grid&gt;
&lt;/sap:ActivityDesigner&gt;
</pre>
<p>And the WriteCell Activity makes the cell value assignment possible from within the workflow diagram. For the WriteCell activity an ExpressionTextBox is used, supporting the InArgument expression possibilities. </p>
<p><a href="http://www.johandekoning.nl/wp-content/uploads/2010/04/ScreenShot005.png"><img src="http://www.johandekoning.nl/wp-content/uploads/2010/04/ScreenShot005.png" alt="" title="Write Cell Activity" width="228" height="80" class="aligncenter size-full wp-image-553" /></a></p>
<pre class="brush: xml; title: ; notranslate">
&lt;sap:ActivityDesigner x:Class=&quot;TuringMachine.Activities.Designer.WriteCellDesigner&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:sap=&quot;clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation&quot;
    xmlns:sapv=&quot;clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation&quot;
    xmlns:conv=&quot;clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation&quot;
    xmlns:local=&quot;clr-namespace:TuringMachine.Activities.Designer&quot;
    xmlns:sys=&quot;clr-namespace:System;assembly=mscorlib&quot;&gt;
  &lt;sap:ActivityDesigner.Resources&gt;
    &lt;conv:ArgumentToExpressionConverter x:Key=&quot;expressionConverter&quot;/&gt;
  &lt;/sap:ActivityDesigner.Resources&gt;
  &lt;Grid&gt;
        &lt;Grid.ColumnDefinitions&gt;
            &lt;ColumnDefinition Width=&quot;auto&quot;/&gt;
            &lt;ColumnDefinition Width=&quot;*&quot;/&gt;
        &lt;/Grid.ColumnDefinitions&gt;
        &lt;Grid.RowDefinitions&gt;
            &lt;RowDefinition Height=&quot;*&quot;/&gt;
        &lt;/Grid.RowDefinitions&gt;
        &lt;TextBlock VerticalAlignment=&quot;Center&quot;&gt;Cell value&lt;/TextBlock&gt;
        &lt;sapv:ExpressionTextBox Grid.Column=&quot;1&quot; Expression=&quot;{Binding Path=ModelItem.CellValue, Mode=TwoWay, ConverterParameter=In, Converter={StaticResource expressionConverter}}&quot; ExpressionType=&quot;{local:NullableExtension sys:Int32}&quot; OwnerActivity=&quot;{Binding Path=ModelItem}&quot;&gt;&lt;/sapv:ExpressionTextBox&gt;
    &lt;/Grid&gt;
&lt;/sap:ActivityDesigner&gt;
</pre>
<h3>Workflow implementation with custom activities</h3>
<p>With the use of the developed custom activities together with their design, the diagram of the workflow will give us directly more information related to the execution of the program</p>
<p><a href="http://www.johandekoning.nl/wp-content/uploads/2010/04/CountingWorkflowWithCustomActivities.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2010/04/CountingWorkflowWithCustomActivities-454x500.jpg" alt="" title="CountingWorkflowWithCustomActivities" width="454" height="500" class="aligncenter size-medium wp-image-555" /></a></p>
<h3>What&#8217;s next?</h3>
<p>My first impression about WF4 is that the usage is more simplified. Within the previous version of WF you had to write a lot of code to execute external methods. With the use of the CodeActivity (or NativeActivity) class it is easy to implement custom activities. The possibility to use XAML to layout your custom activities is very powerful. It makes it possible to implement diagrams which are visual more meaningful (especially useful when hosting the WF designer within your own application). While the FlowChart is not a real State Workflow, it is suitable for the implementation written above. The usage feels more natural, just like developing a sequence workflow.</p>
<p>While developing the counting workflow I had some issues with the support of Nullable types and the ExpressionTextBox. I needed to implement an TypeExtension to make it possible to define the ExpressionType as a Nullable<Int32>. This was not what I expected because XAML 2009 (XAML version of .Net 4) should make it possible to define the type as {x:Type TypeName=System:Nullable`1[[System.Int32]]}. But this syntax is not accepted as valid. </p>
<h3>Source code</h3>
<p>The visual studio 2010 solution including the workflows and source code files can be found at (<a href="http://johandekoning.codeplex.com">http://johandekoning.codeplex.com</a> -> browse to WF/TuringMachine)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2010/04/07/turing-machine-implementation-with-wf4-and-flowchart/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Powershell &#8211; Sync/shift file creation time</title>
		<link>http://www.johandekoning.nl/index.php/2010/03/29/powershell-syncshift-file-creation-time/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=powershell-syncshift-file-creation-time</link>
		<comments>http://www.johandekoning.nl/index.php/2010/03/29/powershell-syncshift-file-creation-time/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 20:56:23 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=525</guid>
		<description><![CDATA[I went on holiday for two weeks together with my girlfriend. We both had our own camera and when we returned home we wanted to merge both photo collections. There was only a small problem, the date/time settings of the cameras were not in sync. This will give you funny/strange results when viewing the slideshow. [...]]]></description>
			<content:encoded><![CDATA[<p>I went on holiday for two weeks together with my girlfriend. We both had our own camera and when we returned home we wanted to merge both photo collections. There was only a small problem, the date/time settings of the cameras were not in sync. This will give you funny/strange results when viewing the slideshow.</p>
<p>To solve this issue, I created a small powershell script. As an argument you provide a datetime string (format ddMMyyyyHHmmss). The oldest file (inside the directory where you execute this script) will get this new provided creation date. The creation date of the other files is updated taken the same time span (between oldest file date and the provided date) into account. Executing this script on one of the photo collections will make it possible to merge both collections.</p>
<pre class="brush: powershell; title: ; notranslate">
$oldestFile = dir | sort-object CreationTime | select -first 1

$newStartDateTime = [datetime]::ParseExact($args,&quot;ddMMyyyyHHmmss&quot;,$null)
$timespan = $newStartDateTime - $oldestFile.CreationTime

dir | foreach { $_.CreationTime = ($_.CreationTime + $timespan)}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2010/03/29/powershell-syncshift-file-creation-time/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My colleague went to a conference and all I got was this lousy eco-button</title>
		<link>http://www.johandekoning.nl/index.php/2010/01/14/my-colleague-went-to-a-conference-and-all-i-got-was-this-lousy-eco-button/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=my-colleague-went-to-a-conference-and-all-i-got-was-this-lousy-eco-button</link>
		<comments>http://www.johandekoning.nl/index.php/2010/01/14/my-colleague-went-to-a-conference-and-all-i-got-was-this-lousy-eco-button/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 22:44:00 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Ecobutton]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=513</guid>
		<description><![CDATA[Today I got an eco button from my colleague. It is a hardware button with a green flashing light (is that eco?) which can be connected to your computer. With software installed, your computer will be put in stand-by mode when you press the button. Because I use my computer the whole day for development, [...]]]></description>
			<content:encoded><![CDATA[<p>Today I got an <em>eco button</em> from my colleague. It is a hardware button with a green flashing light (is that eco?) which can be connected to your computer. With software installed, your computer will be put in stand-by mode when you press the button.</p>
<p><img src="http://www.johandekoning.nl/wp-content/uploads/2010/01/EcoButton_zoom.jpg" alt="" title="Ecobutton" width="350" height="350" class="aligncenter size-full wp-image-514" /></p>
<p>Because I use my computer the whole day for development, I don&#8217;t need an <em>eco-button</em>. I need an <em>build project button</em> for the Visual Studio development environment. A little hack is really easy to make and the result will be a more impressive build routine <img src='http://www.johandekoning.nl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Pressing the button (after connecting it to your computer without installing the ecobutton software) will execute the keys command</p>
<pre>Windows-Key+R ecobutton ENTER</pre>
<p>In my opinion a stupid implementation, because each time you press the button you see a Run dialog, followed by the &#8220;ecobutton&#8221; text filled in and finished with an enter. But this way it is quite easy to replace ecobutton.exe with your own application (keeping the same name)</p>
<p>So I developed a little console application (maybe a hidden application is even better) which will search my Visual Studio application and send the key command F6 (you can also send CTRL+SHIFT+B).</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace WhatDoesThisButtonDo
{
    class Program
    {
        [DllImport(&quot;user32.dll&quot;)]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        static void Main(string[] args)
        {
            IntPtr hWnd = IntPtr.Zero;

            foreach (var p in Process.GetProcesses())
            {
                if (p.ProcessName.Equals(&quot;devenv&quot;)) {
                    hWnd = p.MainWindowHandle;
                    break;
                }
            }

            if (hWnd != IntPtr.Zero)
            {
                SetForegroundWindow(hWnd);
                SendKeys.SendWait(&quot;{F6}&quot;);
            }
        }
    }
}
</pre>
<h3>Explaining the code</h3>
<p>When pressing the ecobutton, Visual Studio is not the active application anymore. Therefore I first have to find the window handler (of Visual Studio), make it the active foreground application and send the F6 key. There is a <em>FindWindow </em>method (user32.dll) but this one is based on the caption on the title bar. Because your solution name is part of this caption, the name is not static. To solve this issue I loop through the different processes to find the <em>devenv</em> process (when multiple visual studio&#8217;s are running, only one is used in this sample).</p>
<p>The <em>SetForegroundWindow </em>brings Visual Studio to the foreground. The F6 key is sent with <em>SendKeys.SendWait</em>. Instead of the F6 key you can also send the CTRL+SHIFT+B keystrokes by supplying &#8220;^+B&#8221;</p>
<p>To use this small applicaton, make sure it is called <em>ecobutton.exe</em> and placed within your <em>PATH</em> (otherwise Windows is unable to find it). </p>
<p>For me the <em>Build button</em> is way better than the <em>Eco button</em> version, but probaly you have better/other implementation suggestions what you can do with this hardware device. Please post them as feedback on this blogpost.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2010/01/14/my-colleague-went-to-a-conference-and-all-i-got-was-this-lousy-eco-button/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Top2OneNote Addin &#8211; Making my digital notepad notes searchable</title>
		<link>http://www.johandekoning.nl/index.php/2009/12/08/top2onenote-addin-making-my-digital-notepad-notes-searchable/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=top2onenote-addin-making-my-digital-notepad-notes-searchable</link>
		<comments>http://www.johandekoning.nl/index.php/2009/12/08/top2onenote-addin-making-my-digital-notepad-notes-searchable/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 22:39:29 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.Net]]></category>
		<category><![CDATA[AddIn]]></category>
		<category><![CDATA[Digital Notepad]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[InkAnalyzer]]></category>
		<category><![CDATA[OneNote]]></category>
		<category><![CDATA[Text recognition]]></category>
		<category><![CDATA[Top]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=490</guid>
		<description><![CDATA[Last week I bought a nice gadget at our discount supermarket (Aldi). The gadget is called a Digital notepad and makes it possible to record your notes while writing them down on paper. Your writing is stored on the internal memory as vector data. There is a lot of software supplied, but using them is [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I bought a nice gadget at our discount supermarket (Aldi). The gadget is called a Digital notepad and makes it possible to record your notes while writing them down on paper. Your writing is stored on the internal memory as vector data. There is a lot of software supplied, but using them is not that straightforward. </p>
<p><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/BILD05.JPG"><img class="aligncenter size-full wp-image-491" title="Digital notepad" src="http://www.johandekoning.nl/wp-content/uploads/2009/12/BILD05.JPG" alt="Digital notepad" width="500" height="500" /></a></p>
<p>Most of the software supplied with this gadget wants to convert the note to clear text. But because of my bad handwriting, most of the time the converted text makes no sense. I also want to keep the drawing which I added to my notes. So instead of converting it to text, I would be happy if I can archive the notes and make them searchable.</p>
<p>Microsoft OneNote gives Tablet PC users the option to add handwritten notes to there OneNote notebook. Those notes are made searchable, while the handwritten note still exists. Instead of using a Tablet PC I want to convert my Digital Notepad content to OneNote handwritten notes. And therefore I developed a small OneNote addin which makes this possible. The source code together with the installer can be found at <a href="http://top2onenote.codeplex.com">http://top2onenote.codeplex.com</a>. Within this blogpost, I will explain some of the steps I took to make this addin possible.</p>
<h2>Reading a TOP file</h2>
<p>There is less information available about the file format that is generated by the Digital Notepad. The file extension is called .Top and it looks like it is a format invented by <a href="http://www.waltop.com.tw/">Waltop International Corp</a>. When searching on the Internet for more information I found this <a href="http://eddie.niese.net/20071129/new-digital-notepad-gadget/">blogpost </a>together with some perl and python scripts to convert a Top file to SVG. I will use the logic of these scripts to convert my notes to OneNote.</p>
<h2>Develop an OneNote AddIn</h2>
<p>Visual Studio 2008 gives you the possiblity to develop Office Add Ins. There are different project templates supplied for Word, Excel and Outlook&#8230; but not for OneNote. There are no Visual Studio templates available for OneNote, so developing a AddIn is not that easy. Again Google gives me a nice search result, a blogpost about creating a toolbar addin for OneNote 2007: http://blogs.msdn.com/descapa/archive/2006/08/31/734298.aspx. There is a step by step tutorial supplied which will explain the different steps to develop a toolbar Addin which will popup a Hello world message. The AddIn will make use of COM Interop, which makes it possible to use C#.</p>
<p>The interface which should be implemented does only contains two methods. I found out that using this interface will only gives you the active OneNote page. With the OneNote.ApplicationClass (part of the Microsoft.Office.OneNote.Interop assembly) you will update the OneNote page outside OneNote. This means that the functionality of your addin does not run within OneNote, but inside a DllHost container.</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using OneNote = Microsoft.Office.Interop.OneNote;

namespace Top2OneNoteAddIn
{
   [ComImport, Guid(&quot;C9590FA7-2132-47fb-9A78-AF0BF19AF4E6&quot;)]
   public interface IOneNoteAddIn
   {
      bool OnClick([In] String strActivePageID);

      bool OnEvent([In] OneNote.OneNoteAddIn_Event evt, [In] String strParameter);
   }
}
</pre>
<p><em>Note: together with OneNote 2007 I also installed the OneNote 2010 Beta. It seems like the AddIn functionality will change, because the addin is shown on the toolbar but clicking on it does not trigger the functionality. I think that with the release of OneNote 2010 that I will be easier to develop OneNote Addins, probably with the use of a Visual Studio template.</em></p>
<h2>OpenFileDialog issue</h2>
<p>The AddIn should, when clicked, open up a file dialog where the user can select the .top file which should be imported. Because the plugin does not run for within OneNote, the <em>OpenFileDialog </em>was shown below the OneNote window. I found a solution by supplying the Windows handler of OneNote as owner of the OpenFileDialog. This way the dialog is shown on top of OneNote</p>
<pre class="brush: csharp; title: ; notranslate">
Process[] procs = Process.GetProcessesByName(&quot;OneNote&quot;);
IntPtr hwnd = procs[0].MainWindowHandle;

OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = &quot;top files (*.top)|*.top|All files (*.*)|*.*&quot;;
dialog.Title = &quot;Select a top file&quot;;
dialog.ShowDialog(new WindowWrapper(hwnd));
</pre>
<p>A little WindowWrapper class is added to the solution, which implements the <em>IWin32Window </em>interface making it possible to supply the window handler as argument to the <em>ShowDialog </em>method.</p>
<pre class="brush: csharp; title: ; notranslate">
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
        private IntPtr _hwnd;

        public WindowWrapper(IntPtr handle)
        {
            _hwnd = handle;
        }

        #region IWin32Window Members

        public IntPtr Handle
        {
            get { return _hwnd; }
        }

        #endregion
}
</pre>
<h2>InkAnalyzer</h2>
<p>The vector data from the top file is converted to a collection of <em>Stroke </em>objects (for which the constructor gets a <em>StylusPointCollection </em>as argument). Those stoke objects are set to the <em>InkAnalyzer</em>. The <em>Analyze </em>method performs layout analysis, writing and drawing classification, and handwriting recognition. The result is given back as an <em>AnalysisStatus </em>object which will be used for building the XML structure used to update the OneNote page.</p>
<pre class="brush: csharp; title: ; notranslate">
InkAnalyzer analyzer = new InkAnalyzer();
analyzer.AddStroke(stroke);

AnalysisStatus status = analyzer.Analyze();
if (status.Successful)
{
   Console.WriteLine(analyzer.GetRecognizedString());
}
</pre>
<p>The AddStroke method has overloaded method for which you can specify the languageId of the stroke. By default the locale settings of the active thread will be used. In my case the Dutch language id was used (because of my region settings). I use English as my OS display language. When the Dutch language pack is not installed, the result of the analyzer will not be successful. So keep in mind to check if the correct language packs are installed to make handwritten recognition possible. The method <em>analyzer.GetInkRecognizersByPriority() </em> gives back a list of available <em>InkRecognizers </em>for the different languages.</p>
<h2>Building the OneNote XML</h2>
<p>You can update OneNote pages by providing a XML structure. Adding or updating depends if objectids are supplied. If this is the case, the object will be updated. An example of the XML used to add the handwritten notes to OneNote</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;one:Page xmlns:one=&quot;http://schemas.microsoft.com/office/onenote/2007/onenote&quot;
        ID=&quot;{C6CCDE4D-7F47-46FA-9DD6-0A4CEC503E86}{1}{B0}&quot;&gt;
	&lt;one:Outline&gt;
		&lt;one:Position x=&quot;209.9905395507812&quot; y=&quot;126.0&quot;/&gt;
		&lt;one:Size width=&quot;245.2818908691406&quot; height=&quot;125.3196716308594&quot;/&gt;
		&lt;one:OEChildren&gt;
			&lt;one:OE&gt;
				&lt;one:InkWord recognizedText=&quot;hallo&quot;&gt;
					&lt;one:Data&gt;AMIGHQSQBOYCAYABKgAaH4tCcEWEdYC+0EXZBFjPVIrml8VPjwb4utLhmyK/
7HHMzCKxQYkOuxMs7nqh3rsTi+Ves0icm6ElWrdREvqHlTLy7BdBuMAWv/Mr9HrEZm2nDbJYSZodTkA0BmwQRVOAL
HoY1USZZUo0BjFbMxSVQJ6SzJhLtWqQHBLFWlUDC0gURSNGI1cNAAAABQcLZU9mZ2hpGRQyCACAHgIh4uJBMwgA
4BICSvPiQRGrqtNBZAMVRgBAShs20YdmzeA0YdmxgA6YdmsBow7GLAB0w7Nm8AAATxMEawMVRgBAahA+gEXPAA
ARXQADggAAIqIAAAqKAW+C/gdb+B19kqxUublEssCwCSiblSgFlABLLFSyypYWLLFlliiC/gR7+BH7ACTZc3LJqblks2W
CzZQ2VNliyklZSMkzVmrKsVKSgNyygAoAESBQIxrXX3TKARMEEgARIKFVgU7sSj5OjNx+XqrpdDQFFEYAQAAABRRGA
QAAAAoAESDcOupAmua8QApiMYL+CJP4IlAAAEoAAEoAgv4BG/gEfKycSbsm5di0qry2bEGy8tUKABEg4IA52V90ygE
TBBIAESCouC8UZctFT6fx0sc+lOXuBRRGAEAAAAUURgFAAAAKP0Aj06oIUjE4DWAKWiGC/gnj+CeQBBZZQACC/gEj
+ARWM5yUt25ddnaFiwAKABEgIH932l90ygETBBIAESAf+viILJADTKojJ+vOFaLHBRRGAEAAAAUURgGAAAAJFiKA30M
Qcv/ZAAp0SYL+BFP4EVAACUALAkJRU3NypSbCwUCC/gDT+ANeJMktzPHc7Le7dtVaNy7WOIgkuJbmpZGrZQAKAB
EgYAtv1V90ygETBBIAESAUVWvkl8H9TbQgjxGuoKlABRRGAEAAAAUURgDAAAAKP0Ai63IF0ksIC+AKggFlgv4MK/gw
25SpYsFlhLAESwlsmybLNypbKAssqWUlllixZYsAgv4EY/gRkAlgZYWWFlEs2WaFUTZVkqJUuUlgAssssVAACgARIGBI
qdtfdMoBEwQSABEgk453gdolgkGItwM1/odLkQUURgBAAAAFFEYBwAAACgARIGLKJkG7kLtA
					&lt;/one:Data&gt;
				&lt;/one:InkWord&gt;
			&lt;/one:OE&gt;
		&lt;/one:OEChildren&gt;
	&lt;/one:Outline&gt;
	&lt;one:Outline&gt;
		&lt;one:Position x=&quot;225.0141754150391&quot; y=&quot;461.2535400390625&quot;/&gt;
		&lt;one:Size width=&quot;680.25830078125&quot; height=&quot;80.7023696899414&quot;/&gt;
		&lt;one:OEChildren&gt;
			&lt;one:OE&gt;
				&lt;one:InkWord recognizedText=&quot;dit&quot;&gt;...
					&lt;/one:Data&gt;
				&lt;/one:InkWord&gt;
				&lt;one:InkWord recognizedText=&quot;is&quot;&gt;
					&lt;one:Data&gt;...
					&lt;/one:Data&gt;
				&lt;/one:InkWord&gt;
				&lt;one:InkWord recognizedText=&quot;een&quot;&gt;
					&lt;one:Data&gt;...&lt;/one:Data&gt;
				&lt;/one:InkWord&gt;
				&lt;one:InkWord recognizedText=&quot;test&quot;&gt;
					&lt;one:Data&gt;...
					&lt;/one:Data&gt;
				&lt;/one:InkWord&gt;
			&lt;/one:OE&gt;
		&lt;/one:OEChildren&gt;
	&lt;/one:Outline&gt;
&lt;/one:Page&gt;
</pre>
<p>Only the data for the first word is shown in this example to keep things clear. At the root element (Page) the ID of the existing page (provided as argument of the OnClick method) to define that the content should be inserted to the page.The InkWord data are stored as Ink Serialized Format with BASE64 encoding and placed together with the recognizedText to make searching within the handwritten notes possible.</p>
<pre class="brush: csharp; title: ; notranslate">
InkWordNode iwNode = node as InkWordNode;

using (MemoryStream ms = new MemoryStream())
{
   iwNode.Strokes.Save(ms);
   byte[] isfBytes = ms.ToArray();
   dataNode.SetValue(Convert.ToBase64String(isfBytes));
}
</pre>
<h2>Updating OneNote</h2>
<p>Updating the OneNote page is done by creating an instance of the OneNote.ApplicationClass. The UpdatePageContent method is used whereby the created XML structure is supplied as argument. There is a little delay between executing the importer and when the page is updated. The cause of this delay is probally that the OneNote page is updated outside OneNote and that it will be triggered to refresh the page content.</p>
<pre class="brush: csharp; title: ; notranslate">
OneNote.ApplicationClass onApplication = new OneNote.ApplicationClass();

XNamespace one = &quot;http://schemas.microsoft.com/office/onenote/2007/onenote&quot;;
XElement root = new XElement(one + &quot;Page&quot;, new XAttribute(XNamespace.Xmlns + &quot;one&quot;, one));
root.Add(new XAttribute(&quot;ID&quot;, strActivePageID));

BuildXML(analyzer.RootNode, root, one);

onApplication.UpdatePageContent(root.ToString(), DateTime.MinValue);
</pre>
<h2>What&#8217;s next?</h2>
<p>The result of the importer is the same when writing the text directly with the use of a Tablet PC. Probably the results of a Tablet PC are maybe even more secure, but that&#8217;s also the reason that I don&#8217;t want to convert the handwritten notes to text. </p>
<div id="attachment_507" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot032.png"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot032-500x348.png" alt="Search within a handwritten note" title="Search within a handwritten note" width="500" height="348" class="size-medium wp-image-507" /></a><p class="wp-caption-text">Search within a handwritten note</p></div>
<p>The importer could be optimized in different ways. Some issues/ideas to improve this add in</p>
<ul>
<li>Language selection &#8211; selected by import or set as a preference</li>
<li>Insert at cursor position &#8211; currently the location is set to the top left. It is possible to retrieve the cursor position by requesting the page content (GetPageContent) with the use of the OneNote.ApplicationClass. The location of the cursor is marked as a selection inside the retrieved XML structure</li>
<li>Improve text recognition &#8211; the InkAnalyzer has different properties to improve the text recognition. This way better results are achieved</li>
<li>Drag and drop support &#8211; instead of using the open file dialog, it would be nice if you can just drag the top file on your OneNote page</li>
</ul>
<p>Like I mentioned, you can find the source at http://top2onenote.codeplex.com. It is not my goal to put a lot of effort in the development of this AddIn. If you are interested in improving this AddIn, send some feedback and I can add you as contributor to this project. If you have other questions, ask them and I will try to answer them. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2009/12/08/top2onenote-addin-making-my-digital-notepad-notes-searchable/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>XMPP and WCF .Net &#8211; Connecting a XMPP client to Openfire</title>
		<link>http://www.johandekoning.nl/index.php/2009/12/01/xmpp-and-wcf-net-connecting-a-xmpp-client-to-openfire/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=xmpp-and-wcf-net-connecting-a-xmpp-client-to-openfire</link>
		<comments>http://www.johandekoning.nl/index.php/2009/12/01/xmpp-and-wcf-net-connecting-a-xmpp-client-to-openfire/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 22:29:00 +0000</pubDate>
		<dc:creator>Johan de Koning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.Net]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[openfire]]></category>
		<category><![CDATA[psi]]></category>
		<category><![CDATA[wcf]]></category>
		<category><![CDATA[xmpp]]></category>

		<guid isPermaLink="false">http://www.johandekoning.nl/?p=465</guid>
		<description><![CDATA[With Openfire installed (http://www.johandekoning.nl/index.php/2009/11/30/xmpp-and-wcf-net-installation-of-openfire/) it is time to create some users and connect with a XMPP client to the server. User management Because of the simple installation, users created on the Openfire server are stored inside the embedded database. To add new users, make sure that the server runs and open the administration console (default [...]]]></description>
			<content:encoded><![CDATA[<p>With Openfire installed (<a href="http://www.johandekoning.nl/index.php/2009/11/30/xmpp-and-wcf-net-installation-of-openfire/">http://www.johandekoning.nl/index.php/2009/11/30/xmpp-and-wcf-net-installation-of-openfire/</a>) it is time to create some users and connect with a XMPP client to the server.</p>
<h2>User management</h2>
<p>Because of the simple installation, users created on the Openfire server are stored inside the embedded database. To add new users, make sure that the server runs and open the administration console (default address http://localhost:9090). </p>
<p><i>Note: I already mentioned this in my previous blog. Within my Vista environment I had to make sure that I start the Openfire server as administrator</i></p>
<p>Within the <em>Administration Console</em>, you will find the <em>Users/Groups</em> section at the top of the page. When you open this section you will get an overview of the users created on the Openfire server</p>
<div id="attachment_472" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot043.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot043-500x297.jpg" alt="User Summary" title="User Summary" width="500" height="297" class="size-medium wp-image-472" /></a><p class="wp-caption-text">User Summary</p></div>
<p>Click on the <em>Create New User</em> option on the left, to create a new user. The <em>Create User</em> page needs some information for the new user. Provide this information and click <em>create user</em> to add the user. Or choose <em>Create &#038; Create another</em> if you want to create another user after this user account is added.</p>
<div id="attachment_474" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot051.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot051-500x449.jpg" alt="Create User" title="Create User" width="500" height="449" class="size-medium wp-image-474" /></a><p class="wp-caption-text">Create User</p></div>
<p>I create two users which are called <strong>user1</strong> and <strong>user2</strong>. I gave the the same password as their username. The overview shows the following user list.</p>
<div id="attachment_475" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot045.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot045-500x353.jpg" alt="User Summary (users created)" title="User Summary (users created)" width="500" height="353" class="size-medium wp-image-475" /></a><p class="wp-caption-text">User Summary (users created)</p></div>
<p>One of the core extensions of the XMPP protocol is the ability to have a user list which is stored on the server (which is called a Roster). Within the Administration Console you can manage those lists, to make it possible that user1 has user2 as a contact and visa versa. This is off course also possible from within a XMPP client where you can add new users. </p>
<p>To manage a contacts list (roster) for a user, click on the username (of the user you want to manage) from the overview. You will get the User Properties screen, with some basic information.</p>
<div id="attachment_476" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot052.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot052-500x382.jpg" alt="User properties" title="User properties" width="500" height="382" class="size-medium wp-image-476" /></a><p class="wp-caption-text">User properties</p></div>
<p>At the left you will find a Roster option. When you click that option, you get an overview of the roster items. These items can be other users, or groups of users. Click the Add New Item (at the right of the screen) to add user 2 to the roster items of user 1. </p>
<div id="attachment_477" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot053.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot053-500x340.jpg" alt="Add roster item" title="Add roster item" width="500" height="340" class="size-medium wp-image-477" /></a><p class="wp-caption-text">Add roster item</p></div>
<p>When added, the user roster overview will show user 2. Perform the same action for user 2 but this time add user 1 to the roster list. </p>
<div id="attachment_478" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot047.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot047-500x353.jpg" alt="User Roster" title="User Roster" width="500" height="353" class="size-medium wp-image-478" /></a><p class="wp-caption-text">User Roster</p></div>
<p>When both users are on both list, the user configuration part is finished. I know it is very basic, but this is jus for development. When can now use a XMPP client to make a connection with our server.</p>
<h2>Using Psi (XMPP Client)</h2>
<p>There are a lot of XMPP clients available on the Internet. I use Psi because it has a nice XML logging feature, to make the XMPP stream visible. I can use this sample stream for development of a XMPP client in .Net without the use of WCF. You can download the Psi client at <a href="http://psi-im.org/download/">http://psi-im.org/download/</a></p>
<p>When you start the client for the first time, it will show you a message that you need to set up an account. Click on the <em>Use existing account</em> option, because our test accounts are already available on the server.</p>
<div id="attachment_479" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot048.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot048-500x139.jpg" alt="Account setup" title="Account setup" width="500" height="139" class="size-medium wp-image-479" /></a><p class="wp-caption-text">Account setup</p></div>
<p>On the first tab (Account) fill in the Jabber ID (JID) and password. The jabber ids for our users are <em>user1@localfire</em> and <em>user2@localfire </em>. The password are <em>user1</em> and <em>user2</em>.</p>
<div id="attachment_480" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot055.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot055-500x365.jpg" alt="Account Tab" title="Account Tab" width="500" height="365" class="size-medium wp-image-480" /></a><p class="wp-caption-text">Account Tab</p></div>
<p>At the connection tab, we need to specify our server location. This is <em>localhost</em> when it runs on the same machine where you installed this client. For testing purposes we will not use an encrypt connection (Never).</p>
<div id="attachment_481" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot058.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot058-500x365.jpg" alt="Connection tab" title="Connection tab" width="500" height="365" class="size-medium wp-image-481" /></a><p class="wp-caption-text">Connection tab</p></div>
<p>Click save to store the account information. The main screen of Psi will be visible whereby the user status is set to Offline.</p>
<div id="attachment_482" class="wp-caption aligncenter" style="width: 215px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot059.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot059.jpg" alt="Psi main screen" title="Psi main screen" width="205" height="396" class="size-full wp-image-482" /></a><p class="wp-caption-text">Psi main screen</p></div>
<p>Before we connect to our Openfire server, I want to enable the XML console to get an idea of the stream which is send between client and server. Right click on the first item of the list (openfire) and select Open XML Console&#8230; Within the XML Console, mark the enable checbox at the bottem left. To get the client connected, select from the dropdownlist at the bottom of the main screen, the Online status. The client will connect to the server and the stream will be made visible in the XML Console dialog.</p>
<div id="attachment_483" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot061.jpg"><img src="http://www.johandekoning.nl/wp-content/uploads/2009/12/ScreenShot061-500x378.jpg" alt="XML Console" title="XML Console" width="500" height="378" class="size-medium wp-image-483" /></a><p class="wp-caption-text">XML Console</p></div>
<h2>The XMPP stream</h2>
<p>I connected another client to the server as user 2. Between both users i send a message with the text &#8220;Hello&#8221; (User 1 -> User 2) and &#8220;Goodbye&#8221; (User 2 -> User 1). The presence of user 1 will be set to Offline and the application will be closed. Below you find the captured XMPP stream. </p>
<h2>What&#8217;s next?</h2>
<p>This blog post explained how to set up the connecting between a XMPP client and server. The captured stream will be used for further analysis. The next step will be the development of a simple XMPP client which will echo back received messages in reverse order. This client will not be written with Windows Communication Foundation to get some feeling how a .Net client with the TcpClient class will work. </p>
<p>If you have questions after reading this post, or have other feedback? Please send in a comment.</p>
<pre class="brush: xml; title: ; notranslate">&lt;!--client--&gt;
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;stream:stream xmlns:stream=&quot;http://etherx.jabber.org/streams&quot; version=&quot;1.0&quot; xmlns=&quot;jabber:client&quot; to=&quot;localfire&quot; xml:lang=&quot;en&quot; xmlns:xml=&quot;http://www.w3.org/XML/1998/namespace&quot; &gt;

&lt;!--server--&gt;
&lt;?xml version='1.0' encoding='UTF-8'?&gt;&lt;stream:stream xmlns:stream=&quot;http://etherx.jabber.org/streams&quot; xmlns=&quot;jabber:client&quot; from=&quot;localfire&quot; id=&quot;c035b19c&quot; xml:lang=&quot;en&quot; version=&quot;1.0&quot;&gt;

&lt;stream:features&gt;
&lt;starttls xmlns=&quot;urn:ietf:params:xml:ns:xmpp-tls&quot;/&gt;
&lt;mechanisms xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;
&lt;mechanism&gt;DIGEST-MD5&lt;/mechanism&gt;
&lt;mechanism&gt;PLAIN&lt;/mechanism&gt;
&lt;mechanism&gt;ANONYMOUS&lt;/mechanism&gt;
&lt;mechanism&gt;CRAM-MD5&lt;/mechanism&gt;
&lt;/mechanisms&gt;
&lt;compression xmlns=&quot;http://jabber.org/features/compress&quot;&gt;
&lt;method&gt;zlib&lt;/method&gt;
&lt;/compression&gt;
&lt;auth xmlns=&quot;http://jabber.org/features/iq-auth&quot;/&gt;
&lt;register xmlns=&quot;http://jabber.org/features/iq-register&quot;/&gt;
&lt;/stream:features&gt;

&lt;!--client--&gt;
&lt;auth xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot; mechanism=&quot;DIGEST-MD5&quot; /&gt;

&lt;!--server--&gt;
&lt;challenge xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;cmVhbG09ImxvY2FsZmlyZSIsbm9uY2U9IitaQVRkeUZNeWJjV1ZveHJHTXNIV2dxNVR1QWhNUkFoQ08wVWlp
VzciLHFvcD0iYXV0aCIsY2hhcnNldD11dGYtOCxhbGdvcml0aG09bWQ1LXNlc3M=&lt;/challenge&gt;

&lt;!--client--&gt;
&lt;response xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;dXNlcm5hbWU9InVzZXIxIixyZWFsbT0ibG9jYWxmaXJlIixub25jZT0iK1pBVGR5Rk15YmNXVm94ckdNc0hXZ3E1
VHVBaE1SQWhDTzBVaWlXNyIsY25vbmNlPSJhM0dMY21ra3VFUjEwaVBTMlJzQnpRZWlBY2pzSnIzNVNyTzRkTFNzM
2FnPSIsbmM9MDAwMDAwMDEsZGlnZXN0LXVyaT0ieG1wcC9sb2NhbGZpcmUiLHFvcD1hdXRoLHJlc3BvbnNlPWM1N
TlhMjBhMmFkZGVjYmJjOTFkZTZkNDYwODYyODU5LGNoYXJzZXQ9dXRmLTg=&lt;/response&gt;

&lt;!--server--&gt;
&lt;success xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;cnNwYXV0aD04NjMxMTIzNDZlM2MxOTUxMGZlNzFmNTA5N2E0MWViMg==&lt;/success&gt;

&lt;!--client--&gt;
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;stream:stream xmlns:stream=&quot;http://etherx.jabber.org/streams&quot; version=&quot;1.0&quot; xmlns=&quot;jabber:client&quot; to=&quot;localfire&quot; xml:lang=&quot;en&quot; xmlns:xml=&quot;http://www.w3.org/XML/1998/namespace&quot; &gt;

&lt;!--server--&gt;
&lt;?xml version='1.0' encoding='UTF-8'?&gt;&lt;stream:stream xmlns:stream=&quot;http://etherx.jabber.org/streams&quot; xmlns=&quot;jabber:client&quot; from=&quot;localfire&quot; id=&quot;c035b19c&quot; xml:lang=&quot;en&quot; version=&quot;1.0&quot;&gt;
&lt;stream:features&gt;
&lt;compression xmlns=&quot;http://jabber.org/features/compress&quot;&gt;
&lt;method&gt;zlib&lt;/method&gt;
&lt;/compression&gt;
&lt;bind xmlns=&quot;urn:ietf:params:xml:ns:xmpp-bind&quot;/&gt;
&lt;session xmlns=&quot;urn:ietf:params:xml:ns:xmpp-session&quot;/&gt;
&lt;/stream:features&gt;

&lt;!--client--&gt;
&lt;iq type=&quot;set&quot; id=&quot;bind_1&quot; &gt;
&lt;bind xmlns=&quot;urn:ietf:params:xml:ns:xmpp-bind&quot;&gt;
&lt;resource&gt;Home&lt;/resource&gt;
&lt;/bind&gt;
&lt;/iq&gt;

&lt;!--server--&gt;
&lt;iq xmlns=&quot;jabber:client&quot; type=&quot;result&quot; id=&quot;bind_1&quot; to=&quot;localfire/c035b19c&quot; &gt;
&lt;bind xmlns=&quot;urn:ietf:params:xml:ns:xmpp-bind&quot;&gt;
&lt;jid&gt;user1@localfire/Home&lt;/jid&gt;
&lt;/bind&gt;
&lt;/iq&gt;

&lt;!--client--&gt;
&lt;iq type=&quot;set&quot; id=&quot;aab7a&quot; &gt;
&lt;session xmlns=&quot;urn:ietf:params:xml:ns:xmpp-session&quot;/&gt;
&lt;/iq&gt;

&lt;!--server--&gt;
&lt;iq type=&quot;result&quot; id=&quot;aab7a&quot; to=&quot;user1@localfire/Home&quot; &gt;
&lt;session xmlns=&quot;urn:ietf:params:xml:ns:xmpp-session&quot;/&gt;
&lt;/iq&gt;

&lt;!--client--&gt;
&lt;iq type=&quot;get&quot; id=&quot;aab8a&quot; &gt;
&lt;query xmlns=&quot;jabber:iq:roster&quot;/&gt;
&lt;/iq&gt;

&lt;!--server--&gt;
&lt;iq type=&quot;result&quot; id=&quot;aab8a&quot; to=&quot;user1@localfire/Home&quot; &gt;
&lt;query xmlns=&quot;jabber:iq:roster&quot;&gt;
&lt;item subscription=&quot;both&quot; jid=&quot;user2@localfire&quot; /&gt;
&lt;/query&gt;
&lt;/iq&gt;

&lt;!--client--&gt;
&lt;presence&gt;
&lt;priority&gt;5&lt;/priority&gt;
&lt;c xmlns=&quot;http://jabber.org/protocol/caps&quot; node=&quot;http://psi-im.org/caps&quot; ver=&quot;0.13-dev-rev2&quot; ext=&quot;ca cs ep-notify html&quot; /&gt;
&lt;/presence&gt;

&lt;iq type=&quot;get&quot; to=&quot;user1@localfire/Home&quot; id=&quot;aabaa&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot; node=&quot;http://psi-im.org/caps#ca&quot; /&gt;
&lt;/iq&gt;

&lt;iq type=&quot;get&quot; id=&quot;aabba&quot; &gt;
&lt;query xmlns=&quot;jabber:iq:private&quot;&gt;
&lt;storage xmlns=&quot;storage:bookmarks&quot;/&gt;
&lt;/query&gt;
&lt;/iq&gt;

&lt;iq type=&quot;get&quot; to=&quot;user1@localfire&quot; id=&quot;aabca&quot; &gt;
&lt;vCard xmlns=&quot;vcard-temp&quot; version=&quot;2.0&quot; prodid=&quot;-//HandGen//NONSGML vGen v1.0//EN&quot; /&gt;
&lt;/iq&gt;

&lt;iq type=&quot;get&quot; to=&quot;localfire&quot; id=&quot;aabda&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot;/&gt;
&lt;/iq&gt;

&lt;!--server--&gt;
&lt;presence from=&quot;user2@localfire/Work&quot; to=&quot;user1@localfire/Home&quot; &gt;
&lt;c xmlns=&quot;http://jabber.org/protocol/caps&quot; node=&quot;http://exodus.jabberstudio.org/caps&quot; ext=&quot;xhtml-im&quot; ver=&quot;0.10.0.0&quot; /&gt;
&lt;priority&gt;1&lt;/priority&gt;
&lt;/presence&gt;

&lt;!--client--&gt;
&lt;iq type=&quot;get&quot; to=&quot;user2@localfire/Work&quot; id=&quot;aabea&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot; node=&quot;http://exodus.jabberstudio.org/caps#0.10.0.0&quot; /&gt;
&lt;/iq&gt;

&lt;iq type=&quot;get&quot; to=&quot;user2@localfire/Work&quot; id=&quot;aabfa&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot; node=&quot;http://exodus.jabberstudio.org/caps#xhtml-im&quot; /&gt;
&lt;/iq&gt;

&lt;!--server--&gt;
&lt;iq from=&quot;user1@localfire/Home&quot; type=&quot;get&quot; to=&quot;user1@localfire/Home&quot; id=&quot;aabaa&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot; node=&quot;http://psi-im.org/caps#ca&quot; /&gt;
&lt;/iq&gt;

&lt;!--client--&gt;
&lt;iq type=&quot;result&quot; to=&quot;user1@localfire/Home&quot; id=&quot;aabaa&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot; node=&quot;http://psi-im.org/caps#ca&quot; &gt;
&lt;identity category=&quot;client&quot; type=&quot;pc&quot; name=&quot;Psi&quot; /&gt;
&lt;feature var=&quot;urn:xmpp:jingle:1&quot; /&gt;
&lt;feature var=&quot;urn:xmpp:jingle:transports:ice-udp:1&quot; /&gt;
&lt;feature var=&quot;urn:xmpp:jingle:apps:rtp:1&quot; /&gt;
&lt;feature var=&quot;urn:xmpp:jingle:apps:rtp:audio&quot; /&gt;
&lt;/query&gt;
&lt;/iq&gt;

&lt;!--server--&gt;
&lt;iq type=&quot;result&quot; id=&quot;aabba&quot; to=&quot;user1@localfire/Home&quot; &gt;
&lt;query xmlns=&quot;jabber:iq:private&quot;&gt;

&lt;storage xmlns=&quot;storage:bookmarks&quot;/&gt;
&lt;/query&gt;
&lt;/iq&gt;

&lt;iq from=&quot;user1@localfire&quot; type=&quot;result&quot; id=&quot;aabca&quot; to=&quot;user1@localfire/Home&quot; &gt;
&lt;vCard xmlns=&quot;vcard-temp&quot; version=&quot;2.0&quot; prodid=&quot;-//HandGen//NONSGML vGen v1.0//EN&quot; &gt;
&lt;FN&gt;User 1&lt;/FN&gt;
&lt;/vCard&gt;
&lt;/iq&gt;

&lt;iq from=&quot;localfire&quot; type=&quot;result&quot; id=&quot;aabda&quot; to=&quot;user1@localfire/Home&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot;&gt;
&lt;identity category=&quot;server&quot; type=&quot;im&quot; name=&quot;Openfire Server&quot; /&gt;
&lt;identity category=&quot;pubsub&quot; type=&quot;pep&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#manage-subscriptions&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#modify-affiliations&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#retrieve-default&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#collections&quot; /&gt;
&lt;feature var=&quot;jabber:iq:private&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/disco#items&quot; /&gt;
&lt;feature var=&quot;vcard-temp&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#publish&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#subscribe&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#retract-items&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/offline&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#meta-data&quot; /&gt;
&lt;feature var=&quot;jabber:iq:register&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#retrieve-subscriptions&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#default_access_model_open&quot; /&gt;
&lt;feature var=&quot;jabber:iq:roster&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#config-node&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/address&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#publisher-affiliation&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#item-ids&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#instant-nodes&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/commands&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#multi-subscribe&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#outcast-affiliation&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#get-pending&quot; /&gt;
&lt;feature var=&quot;google:jingleinfo&quot; /&gt;
&lt;feature var=&quot;jabber:iq:privacy&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#subscription-options&quot; /&gt;
&lt;feature var=&quot;jabber:iq:last&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#create-and-configure&quot; /&gt;
&lt;feature var=&quot;urn:xmpp:ping&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#retrieve-items&quot; /&gt;
&lt;feature var=&quot;jabber:iq:time&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#create-nodes&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#persistent-items&quot; /&gt;
&lt;feature var=&quot;jabber:iq:version&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#presence-notifications&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#retrieve-affiliations&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#delete-nodes&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/pubsub#purge-nodes&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/disco#info&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/rsm&quot; /&gt;
&lt;/query&gt;
&lt;/iq&gt;

&lt;iq from=&quot;user2@localfire/Work&quot; type=&quot;result&quot; id=&quot;aabea&quot; to=&quot;user1@localfire/Home&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot; node=&quot;http://exodus.jabberstudio.org/caps#0.10.0.0&quot; &gt;
&lt;feature var=&quot;jabber:iq:agents&quot; /&gt;
&lt;feature var=&quot;jabber:iq:oob&quot; /&gt;
&lt;feature var=&quot;jabber:iq:browse&quot; /&gt;
&lt;feature var=&quot;jabber:iq:time&quot; /&gt;
&lt;feature var=&quot;jabber:iq:version&quot; /&gt;
&lt;feature var=&quot;jabber:iq:last&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/disco#items&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/disco#info&quot; /&gt;
&lt;feature var=&quot;storage:bookmarks&quot; /&gt;
&lt;feature var=&quot;jabber:x:data&quot; /&gt;
&lt;feature var=&quot;jabber:x:conference&quot; /&gt;
&lt;feature var=&quot;jabber:x:event&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/muc&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/muc#user&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/muc#owner&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/si&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/si/profile/file-transfer&quot; /&gt;
&lt;feature var=&quot;http://jabber.org/protocol/bytestreams&quot; /&gt;
&lt;/query&gt;
&lt;/iq&gt;

&lt;iq from=&quot;user2@localfire/Work&quot; type=&quot;result&quot; id=&quot;aabfa&quot; to=&quot;user1@localfire/Home&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot; node=&quot;http://exodus.jabberstudio.org/caps#xhtml-im&quot; &gt;
&lt;feature var=&quot;http://jabber.org/protocol/xhtml-im&quot; /&gt;
&lt;/query&gt;
&lt;/iq&gt;

&lt;iq from=&quot;user1@localfire/Home&quot; type=&quot;result&quot; to=&quot;user1@localfire/Home&quot; id=&quot;aabaa&quot; &gt;
&lt;query xmlns=&quot;http://jabber.org/protocol/disco#info&quot; node=&quot;http://psi-im.org/caps#ca&quot; &gt;
&lt;identity category=&quot;client&quot; type=&quot;pc&quot; name=&quot;Psi&quot; /&gt;
&lt;feature var=&quot;urn:xmpp:jingle:1&quot; /&gt;
&lt;feature var=&quot;urn:xmpp:jingle:transports:ice-udp:1&quot; /&gt;
&lt;feature var=&quot;urn:xmpp:jingle:apps:rtp:1&quot; /&gt;
&lt;feature var=&quot;urn:xmpp:jingle:apps:rtp:audio&quot; /&gt;
&lt;/query&gt;
&lt;/iq&gt;

&lt;!--client--&gt;
&lt;message type=&quot;chat&quot; to=&quot;user2@localfire&quot; id=&quot;aac0a&quot; &gt;
&lt;body&gt;Hello&lt;/body&gt;
&lt;active xmlns=&quot;http://jabber.org/protocol/chatstates&quot;/&gt;
&lt;/message&gt;

&lt;!--server--&gt;
&lt;message from=&quot;user2@localfire/Work&quot; type=&quot;chat&quot; id=&quot;jcl_13&quot; to=&quot;user1@localfire/Home&quot; &gt;
&lt;body&gt;Goodbye&lt;/body&gt;
&lt;x xmlns=&quot;jabber:x:event&quot;&gt;
&lt;composing/&gt;
&lt;/x&gt;
&lt;html xmlns=&quot;http://jabber.org/protocol/xhtml-im&quot;&gt;
&lt;body xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;p style=&quot;font-size:small;font-family:Arial;color:#000000&quot; &gt;Goodbye&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/message&gt;

&lt;!--client--&gt;
&lt;presence type=&quot;unavailable&quot; &gt;
&lt;status&gt;Logged out&lt;/status&gt;
&lt;/presence&gt;

&lt;/stream:stream&gt;

&lt;!--server--&gt;
&lt;/stream:stream&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.johandekoning.nl/index.php/2009/12/01/xmpp-and-wcf-net-connecting-a-xmpp-client-to-openfire/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

