tag:blogger.com,1999:blog-46817722869905455672024-03-13T00:26:53.426+01:00HCanberHåkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-4681772286990545567.post-6827791143707383952014-10-26T17:28:00.001+01:002014-10-26T17:28:01.384+01:00Integration Testing using Akka.NET's TestKit<p>In <a href="/2014/10/getting-started-with-akkanet.html">Getting Started with Akka.NET</a> and <a href="/2014/10/handling-messages-and-state-with-akkanet.html">Handling messages and state with Akka.NET</a> we created a calculator in Akka.NET that was able to add and subtract numbers and return the answer. It also stores the last answer and can respond with it when asked.</p>
<p>In <a href="/2014/10/introducing-testkit-for-akkanet.html">Unit Testing using Akka.NET’s TestKit </a> we created some unit tests to verify internal state of the actor.</p>
<p>In this post we’ll switch to integration tests – verifying we get correct messages back.</p>
<p><strong>Code</strong> for this post: <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/04-calculator-testkit-integration">https://github.com/HCanber/akka.net-blog-examples/tree/master/04-calculator-testkit-integration</a></p>
<p>All posts in this series: <a href="/p/akkanet.html">Tutorials for Akka.NET</a></p>
<blockquote>
<p><strong>Note!</strong> This post was written using Akka.NET 0.7.0 and might not work for later versions</p>
</blockquote>
<h3 id="unit-testing-recap">Unit Testing Recap</h3>
<p><a href="/2014/10/introducing-testkit-for-akkanet.html">Unit Testing using Akka.NET’s TestKit </a> we created some unit tests to verify internal state of the actor. We used <code>ActorOfAsTestActorRef<T>()</code> which creates the actor in the test’s <code>ActorSystem</code> (which is exposed thru the property <code>Sys</code> inside tests) and returns a <code>TestActorRef<T></code> which give us access to the underlycing actor instance using the property <code>UnderlyingActor</code>.</p>
<pre class="prettyprint"><code class="language-C# hljs cs">[Fact]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Answer_should_initially_be_0</span>()
{
TestActorRef<CalculatorActor> calculatorRef = ActorOfAsTestActorRef<CalculatorActor>(<span class="hljs-string">"calculator"</span>);
CalculatorActor calculator = calculatorRef.UnderlyingActor;
Assert.Equal(<span class="hljs-number">0</span>, calculator.Answer);
}
[Fact]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">After_adding_1_and_1_Answer_should_be_2</span>()
{
TestActorRef<CalculatorActor> calculatorRef = ActorOfAsTestActorRef<CalculatorActor>(<span class="hljs-string">"calculator"</span>);
calculatorRef.Tell(<span class="hljs-keyword">new</span> Add(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>));
CalculatorActor calculator = calculatorRef.UnderlyingActor;
Assert.Equal(<span class="hljs-number">2</span>, calculator.Answer);
}</code></pre>
<blockquote>
<p>Remember that everything is synchronous when writing these kind of tests. It’s the use of <code>ActorOfAsTestActorRef<T>()</code> that makes it synchronous. A <code>CallingThreadDispatcher</code> is used for actors created using <code>ActorOfAsTestActorRef<T>()</code> so when we send it a message using <code>Tell(message)</code> it’s not dispatched on another thread, but instead immediately processed before <code>Tell</code> returns control back to our test.</p>
</blockquote>
<h3 id="integration-tests">Integration tests</h3>
<p>When writing integration tests, we create and run the actor the way we normally do. This means multi threaded under full concurrency (actors are shielded by the Actor model – the actor only processes on message at a time).</p>
<h3 id="the-first-test-getlastanswer-should-initially-respond-with-answer0">The first test: GetLastAnswer should initially respond with Answer(0)</h3>
<p>In our first unit test we verfied that the internal state <code>answer</code> is 0 initially. We can also verify this by sending the actor a <code>GetLastAnswer</code> message and verify that we get an <code>Answer(0)</code> back.</p>
<p>The skeleton for the test looks like this:</p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> CalculatorIntegrationTests : TestKit
{
[Fact]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Answer_should_initially_be_0</span>()
{
<span class="hljs-keyword">var</span> calculator = ActorOf<CalculatorActor>(<span class="hljs-string">"calculator"</span>);
calculator.Tell(GetLastAnswer.Instance);
<span class="hljs-comment">//Somehow verify we get an Anser(0) back </span>
}
}</code></pre>
<p>So how can we verify that the calculator responds with what we expect? We could use <code>Ask</code> but there is a better way using TestKit.</p>
<h3 id="testactor">TestActor</h3>
<p>When the TestKit’s <code>ActorSystem</code> is created it also creates a special actor called <code>TestActor</code>. This instance is used as an implicit sender, so when we sent a message to calculator like this:</p>
<pre class="prettyprint"><code class="language-C# hljs avrasm">calculator<span class="hljs-preprocessor">.Tell</span>(GetLastAnswer<span class="hljs-preprocessor">.Instance</span>)<span class="hljs-comment">;</span></code></pre>
<p>It was actually sent as if we’d specified <code>TestActor</code> as the sender:</p>
<pre class="prettyprint"><code class="language-C# hljs avrasm">calculator<span class="hljs-preprocessor">.Tell</span>(GetLastAnswer<span class="hljs-preprocessor">.Instance</span>, TestActor)<span class="hljs-comment">;</span></code></pre>
<p>So when calculator send the response it will send it to <code>TestActor</code> which in turn will put the message in a queue that we can test against.</p>
<div class="sequence-diagram"><svg height="255.46875" version="1.1" width="576.53125" xmlns="http://www.w3.org/2000/svg" style="overflow: hidden; position: relative; top: -0.97442626953125px;"><desc style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Created with Raphaël 2.1.0</desc><defs style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><marker id="raphael-marker-endblock55" markerHeight="5" markerWidth="5" orient="auto" refX="2.5" refY="2.5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><use xlink:href="#raphael-marker-block" transform="rotate(180 2.5 2.5) scale(1,1)" stroke-width="1.0000" fill="#000" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></use></marker></defs><rect x="10" y="20" width="46.84375" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="20" y="30" width="26.84375" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="33.421875" y="39.546875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Test</tspan></text><rect x="10" y="196.375" width="46.84375" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="20" y="206.375" width="26.84375" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="33.421875" y="215.921875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Test</tspan></text><path fill="none" stroke="#000000" d="M33.421875,59.09375L33.421875,196.375" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><rect x="224.171875" y="20" width="85" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="234.171875" y="30" width="65" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="266.671875" y="39.546875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Calculator</tspan></text><rect x="224.171875" y="196.375" width="85" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="234.171875" y="206.375" width="65" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="266.671875" y="215.921875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Calculator</tspan></text><path fill="none" stroke="#000000" d="M266.671875,59.09375L266.671875,196.375" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><rect x="329.171875" y="20" width="80.25" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="339.171875" y="30" width="60.25" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="369.296875" y="39.546875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">TestActor</tspan></text><rect x="329.171875" y="196.375" width="80.25" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="339.171875" y="206.375" width="60.25" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="369.296875" y="215.921875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">TestActor</tspan></text><path fill="none" stroke="#000000" d="M369.296875,59.09375L369.296875,196.375" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><rect x="487.0625" y="20" width="59.46875" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="497.0625" y="30" width="39.46875" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="516.796875" y="39.546875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">queue</tspan></text><rect x="487.0625" y="196.375" width="59.46875" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="497.0625" y="206.375" width="39.46875" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="516.796875" y="215.921875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">queue</tspan></text><path fill="none" stroke="#000000" d="M516.796875,59.09375L516.796875,196.375" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><rect x="43.421875" y="74.546875" width="213.25" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="150.046875" y="84.09375" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">GetLastAnswer, Sender=TestActor</tspan></text><path fill="none" stroke="#000000" d="M33.421875,98.1875C33.421875,98.1875,227.78446908295155,98.1875,261.6650579929192,98.1875" stroke-width="2" marker-end="url(#raphael-marker-endblock55)" stroke-dasharray="0" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><rect x="286.671875" y="113.640625" width="62.625" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="317.984375" y="123.1875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Answer(0)</tspan></text><path fill="none" stroke="#000000" d="M266.671875,137.28125C266.671875,137.28125,343.71701929718256,137.28125,364.29499484921325,137.28125" stroke-width="2" marker-end="url(#raphael-marker-endblock55)" stroke-dasharray="0" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><rect x="379.296875" y="152.734375" width="127.5" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="443.046875" y="162.28125" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Enqueues Answer(0)</tspan></text><path fill="none" stroke="#000000" d="M369.296875,176.375C369.296875,176.375,486.03934049606323,176.375,511.80476745124906,176.375" stroke-width="2" marker-end="url(#raphael-marker-endblock55)" stroke-dasharray="0" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg></div>
<p>To test that the queue contains the correct message, or another way of seeing it: that <code>TestActor</code> received the correct message we use <code>ExpectMessage<T>()</code> and then assert that the value is correct.</p>
<pre class="prettyprint"><code class="language-C# hljs cs">[Fact]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Answer_should_initially_be_0</span>()
{
<span class="hljs-keyword">var</span> calculator = ActorOf<CalculatorActor>(<span class="hljs-string">"calculator"</span>);
calculator.Tell(GetLastAnswer.Instance);
<span class="hljs-keyword">var</span> answer = ExpectMsg<Answer>();
Assert.Equal(<span class="hljs-number">0</span>, answer.Value);
}</code></pre>
<p>The last two lines can also be written like this:</p>
<pre class="prettyprint"><code class="language-C# hljs autohotkey">ExpectMsg<Answer>(<span class="hljs-literal">a</span> => <span class="hljs-literal">a</span>.Value == <span class="hljs-number">0</span>)<span class="hljs-comment">;</span></code></pre>
<h3 id="isnt-it-asynchronous">Isn’t it asynchronous?</h3>
<p>We send a message to <code>calculator</code> which will process the message on another thread. At the same time we test that we have received a response. How can we be sure that the calculator has responded before we execute <code>ExpectMessage<Answer>()</code>? Don’t we need to synchronize somehow? Or is ir running synchronously as with unit tests?</p>
<p>No, it really is asynchronous, BUT <code>ExpectMsg</code> will wait up to 3 seconds before it fails.</p>
<h3 id="verifying-add">Verifying Add</h3>
<p>Rewriting the second unit test as a integration test is really easy now that we have all building blocks.</p>
<pre class="prettyprint"><code class="language-C# hljs cs"> [Fact]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">After_adding_1_and_1_Answer_should_be_2</span>()
{
<span class="hljs-keyword">var</span> calculator = ActorOf<CalculatorActor>(<span class="hljs-string">"calculator"</span>);
calculator.Tell(<span class="hljs-keyword">new</span> Add(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>));
<span class="hljs-keyword">var</span> answer = ExpectMsg<Answer>();
Assert.Equal(<span class="hljs-number">2</span>, answer.Value);
}</code></pre>
<blockquote>
<p>Be aware that the tests run in a full <code>ActorSystem</code> and everything is asynchronous even though it might look like synchronous code.</p>
</blockquote>
<h3 id="code">Code</h3>
<p>Code on GitHub: <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/04-calculator-testkit-integration">https://github.com/HCanber/akka.net-blog-examples/tree/master/04-calculator-testkit-integration</a></p>
<p>All posts in this series: <a href="/p/akkanet.html">Tutorials for Akka.NET</a></p>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com1tag:blogger.com,1999:blog-4681772286990545567.post-48438857320149153962014-10-26T16:42:00.001+01:002014-10-26T16:46:16.905+01:00Unit Testing using Akka.NET's TestKit<p>In <a href="/2014/10/getting-started-with-akkanet.html">Getting Started with Akka.NET</a> and <a href="/2014/10/handling-messages-and-state-with-akkanet.html">Handling messages and state with Akka.NET</a> we created a calculator in Akka.NET that was able to add and subtract numbers and return the answer. It also stores the last answer and can respond with it when asked.</p>
<p>In this post we’ll introduce TestKit which will enable us to write unit and integration tests.</p>
<p><strong>Code</strong> for this post: <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/03-calculator-testkit-unit">https://github.com/HCanber/akka.net-blog-examples/tree/master/03-calculator-testkit-unit</a></p>
<p>All posts in this series: <a href="/p/akkanet.html">Tutorials for Akka.NET</a></p>
<blockquote>
<p><strong>Note!</strong> This post was written using Akka.NET 0.7.0 and might not work for later versions</p>
</blockquote>
<h3 id="testkit">TestKit</h3>
<p>TestKit is a module that allows us to write two types of tests:</p>
<ul>
<li>Testing isolated pieces of code without involving the actor model, meaning without multiple threads; this implies completely deterministic behavior concerning the ordering of events and no concurrency concerns and will be called <strong>Unit Testing</strong> in the following.</li>
<li>Testing (multiple) encapsulated actors including multi-threaded scheduling; this implies non-deterministic order of events but shielding from concurrency concerns by the actor model and will be called <strong>Integration Testing</strong> in the following.</li>
</ul>
<p>In Akka.NET TestKit is distributed in two nuget packages. First you need <code>Akka.TestKit</code> which contains all base functionality and then you need one targeted for a specific Test framework. At the time of writing, we have nuget packages for two frameworks: xUnit and VSTest/MSTest: <code>Akka.TestKit.Xunit</code> and <code>Akka.TestKit.VsTest</code></p>
<h3 id="add-a-test-project">Add a test project</h3>
<p>We’ll continue with the code from <a href="/2014/10/handling-messages-and-state-with-akkanet.html">Handling messages and state with Akka.NET</a> which can be found on <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/02-calculator">GitHub</a> by adding a xUnit test project. The result can also be found on <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/03-calculator-testkit-unit">GitHub</a>.</p>
<p>Start by adding a new Class Library project to the solution. We’ll call it <code>Calculator.Tests</code>. Delete <code>Class1.cs</code> from the project.</p>
<h3 id="add-akkatestkitxunit-to-the-project">Add Akka.TestKit.XUnit to the project</h3>
<p>Add the package <code>Akka.TestKit.XUnit</code> to the test project </p>
<pre class="prettyprint"><code class=" hljs avrasm">Install-Package Akka<span class="hljs-preprocessor">.TestKit</span><span class="hljs-preprocessor">.Xunit</span></code></pre>
<p>This will install all packages needed (<code>Akka</code>, <code>Akka.TestKit</code>, <code>xunit</code>). <br>
Add a reference to the console app project.</p>
<h3 id="create-the-first-test-class">Create the first test class</h3>
<p>Create a new class, inherit from <code>TestKit</code></p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">using</span> Akka.TestKit.Xunit;
<span class="hljs-keyword">using</span> CalculatorApp;
<span class="hljs-keyword">using</span> Xunit;
namespace Calculator.Tests
{
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> CalculatorUnitTests : TestKit
{
}
}
</code></pre>
<p>Now we’re good to go!</p>
<h3 id="testkits-test-system">TestKit’s test system</h3>
<p>When writing tests using TestKit (by inheriting from <code>TestKit</code>) it creates an <code>ActorSystem</code> for us in which the tests are run, so you do not need to create one yourself.</p>
<p>The system can be accessed using <code>Sys</code>. This means that to create an actor in this system you’d do:</p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">var</span> calculator = Sys.ActorOf<CalculatorActor>(<span class="hljs-string">"calculator"</span>);</code></pre>
<p>Since this is done so frequently in tests you can skip the <code>Sys</code> property:</p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">var</span> calculator = ActorOf<CalculatorActor>(<span class="hljs-string">"calculator"</span>);</code></pre>
<h3 id="unit-testing-actors-using-testactorref">Unit testing actors using TestActorRef</h3>
<p>Unit testing actors is when we have full control over the order messages are processed, no concurrency and everything is synchronous. TestKit also provides a way to actually verify internal state of an actor.</p>
<p>Normally, when we create an actor like this we don’t get access to it’s internal state since the proxy <code>ActorRef</code> is returned:</p>
<pre class="prettyprint"><code class="language-C# hljs perl">ActorRef calculator = <span class="hljs-keyword">system</span>.ActorOf<CalculatorActor>(<span class="hljs-string">"calculator"</span>);</code></pre>
<p>When using TestKit there is an overload that returns a <code>TestActorRef<TActor></code> which gives as access to the underlying actor instance via the property <code>UnderlyingActor</code>.</p>
<h3 id="the-first-test-internal-state-answer-should-be-0-initially">The first test: Internal state answer should be 0 initially</h3>
<p>Right after a calculator has been created it’s internal stored answer should be 0. To verify this is true, we need to make some changes to <code>CalculatorActor</code> so we can access the <code>answer</code> value. The local variable <code>answer</code> is turned into a private field, and we add an <code>Answer</code> property:</p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> CalculatorActor : ReceiveActor
{
<span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> _answer;
<span class="hljs-keyword">public</span> <span class="hljs-title">CalculatorActor</span>()
{
Receive<Add>(add =>
{
_answer = add.Term1 + add.Term2;
Sender.Tell(<span class="hljs-keyword">new</span> Answer(_answer));
});
Receive<Subtract>(sub =>
{
_answer = sub.Term1 - sub.Term2;
Sender.Tell(<span class="hljs-keyword">new</span> Answer(_answer));
});
Receive<GetLastAnswer>(m => Sender.Tell(<span class="hljs-keyword">new</span> Answer(_answer)));
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> Answer { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _answer; } }
}</code></pre>
<p>Now we can write the test:</p>
<pre class="prettyprint"><code class="language-C# hljs cs">[Fact]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Answer_should_initially_be_0</span>()
{
TestActorRef<CalculatorActor> calculatorRef = ActorOfAsTestActorRef<CalculatorActor>(<span class="hljs-string">"calculator"</span>);
CalculatorActor calculator = calculatorRef.UnderlyingActor;
Assert.Equal(<span class="hljs-number">0</span>, calculator.Answer);
}</code></pre>
<p>Instead of <code>ActorOf<CalculatorActor></code> we use <code>ActorOfAsTestActorRef<CalculatorActor></code> which returns <code>TestActorRef<CalculatorActor></code>. This type exposes the underlying actor in the <code>UnderlyingActor</code> property. <br>
Once we got hold of it we verify that the <code>Answer</code> is 0.</p>
<p>If we run this test it passes.</p>
<h3 id="verifying-that-state-is-modified-after-handling-messages">Verifying that state is modified after handling messages</h3>
<p>The <code>CalculatorActor</code> should always store the latest answer. So of we send it <code>Add(1,1)</code> the <code>Answer</code> property should be 2. </p>
<pre class="prettyprint"><code class="language-C# hljs cs">[Fact]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">After_adding_1_and_1_Answer_should_be_2</span>()
{
TestActorRef<CalculatorActor> calculatorRef = ActorOfAsTestActorRef<CalculatorActor>(<span class="hljs-string">"calculator"</span>);
calculatorRef.Tell(<span class="hljs-keyword">new</span> Add(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>));
CalculatorActor calculator = calculatorRef.UnderlyingActor;
Assert.Equal(<span class="hljs-number">2</span>, calculator.Answer);
}</code></pre>
<blockquote>
<p>Remember that everything is synchronous when writing these kind of tests. It’s the use of <code>ActorOfAsTestActorRef<T>()</code> that makes it synchronous. A <code>CallingThreadDispatcher</code> is used for actors created using <code>ActorOfAsTestActorRef<T>()</code> so when we send it a message using <code>Tell(message)</code> it’s not dispatch on another thread, but immediately processed before <code>Tell</code> returns control back to our test.</p>
</blockquote>
<h3 id="code">Code</h3>
<p>Code on GitHub: <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/03-calculator-testkit-unit">https://github.com/HCanber/akka.net-blog-examples/tree/master/03-calculator-testkit-unit</a></p>
<p>All posts in this series: <a href="/p/akkanet.html">Tutorials for Akka.NET</a></p>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-31508677818420789012014-10-26T14:46:00.001+01:002014-10-26T15:48:58.993+01:00Handling messages and state with Akka.NET<p>In <a href="/2014/10/getting-started-with-akkanet.html">Getting Started with Akka.NET</a> we created a calculator in Akka.NET that was able to add two numbers and return the response.</p>
<p>In this post we’ll add more functionality to the calculator.</p>
<p><strong>Code</strong> for this post: <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/02-calculator">https://github.com/HCanber/akka.net-blog-examples/tree/master/02-calculator</a></p>
<p>All posts in this series: <a href="/p/akkanet.html">Tutorials for Akka.NET</a></p>
<blockquote>
<p><strong>Note!</strong> This post was written using Akka.NET 0.7.0 and might not work for later versions</p>
</blockquote>
<h4 id="receiving-more-messages">Receiving more messages</h4>
<p>The calculator should be able to subtract two values as well, so create a copy of the <code>Add</code> class and rename it to <code>Subtract</code></p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> Subtract
{
<span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">double</span> _term1;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">double</span> _term2;
<span class="hljs-keyword">public</span> <span class="hljs-title">Subtract</span>(<span class="hljs-keyword">double</span> term1, <span class="hljs-keyword">double</span> term2)
{
_term1 = term1;
_term2 = term2;
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> Term1 { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _term1; } }
<span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> Term2 { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _term2; } }
}</code></pre>
<p>We make the fields readonly to ensure the message is immutable.</p>
<p>Next, we need to tell <code>CalculatorActor</code> how to handle <code>Subtract</code> messages by adding another <code>Receive</code> statement:</p>
<pre class="prettyprint"><code class="language-C# hljs avrasm">public class CalculatorActor : ReceiveActor
{
public CalculatorActor()
{
Receive<<span class="hljs-keyword">Add</span>>(<span class="hljs-keyword">add</span> => Sender<span class="hljs-preprocessor">.Tell</span>(new Answer(<span class="hljs-keyword">add</span><span class="hljs-preprocessor">.Term</span>1 + <span class="hljs-keyword">add</span><span class="hljs-preprocessor">.Term</span>2)))<span class="hljs-comment">;</span>
Receive<Subtract>(<span class="hljs-keyword">sub</span>=> Sender<span class="hljs-preprocessor">.Tell</span>(new Answer(<span class="hljs-keyword">sub</span><span class="hljs-preprocessor">.Term</span>1 - <span class="hljs-keyword">sub</span><span class="hljs-preprocessor">.Term</span>2)))<span class="hljs-comment">;</span>
}
}</code></pre>
<p>You can have as many <code>Receive</code> statements you like, but be aware of that the order is important. The upper takes precedence over the lower. In this case it doesn’t matter, but if we were to insert a <code>Receive<object></code> first, it would handle ALL messages, and our handlers for Add and Subtract would never be called.</p>
<h4 id="testing-subtraction">Testing subtraction</h4>
<p>We add two more lines to test subtraction:</p>
<pre class="prettyprint"><code class="language-C# hljs avrasm">static void Main(string[] args)
{
var system = ActorSystem<span class="hljs-preprocessor">.Create</span>(<span class="hljs-string">"calculator-system"</span>)<span class="hljs-comment">;</span>
var calculator = system<span class="hljs-preprocessor">.ActorOf</span><CalculatorActor>(<span class="hljs-string">"calculator"</span>)<span class="hljs-comment">;</span>
var answer = calculator<span class="hljs-preprocessor">.Ask</span><Answer>(new <span class="hljs-keyword">Add</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>))<span class="hljs-preprocessor">.Result</span><span class="hljs-comment">;</span>
Console<span class="hljs-preprocessor">.WriteLine</span>(<span class="hljs-string">"1 + 2 = "</span> + answer<span class="hljs-preprocessor">.Value</span>)<span class="hljs-comment">;</span>
var answerSubtract = calculator<span class="hljs-preprocessor">.Ask</span><Answer>(new Subtract(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>))<span class="hljs-preprocessor">.Result</span><span class="hljs-comment">;</span>
Console<span class="hljs-preprocessor">.WriteLine</span>(<span class="hljs-string">"5 - 3 = "</span> + answerSubtract<span class="hljs-preprocessor">.Value</span>)<span class="hljs-comment">;</span>
Console<span class="hljs-preprocessor">.WriteLine</span>(<span class="hljs-string">"Press any key to exit"</span>)<span class="hljs-comment">;</span>
Console<span class="hljs-preprocessor">.ReadKey</span>()<span class="hljs-comment">;</span>
}</code></pre>
<h4 id="adding-state">Adding state</h4>
<p>Let’s add some state to our <code>CalculatorActor</code>. Every time it has performed a calculation it should store the answer. We modify the actor to look like this.</p>
<pre class="prettyprint"><code class="language-C# hljs avrasm"> public class CalculatorActor : ReceiveActor
{
public CalculatorActor()
{
var answer = <span class="hljs-number">0</span>d<span class="hljs-comment">;</span>
Receive<<span class="hljs-keyword">Add</span>>(<span class="hljs-keyword">add</span> =>
{
answer = <span class="hljs-keyword">add</span><span class="hljs-preprocessor">.Term</span>1 + <span class="hljs-keyword">add</span><span class="hljs-preprocessor">.Term</span>2<span class="hljs-comment">;</span>
Sender<span class="hljs-preprocessor">.Tell</span>(new Answer(answer))<span class="hljs-comment">;</span>
})<span class="hljs-comment">;</span>
Receive<Subtract>(<span class="hljs-keyword">sub</span> =>
{
answer = <span class="hljs-keyword">sub</span><span class="hljs-preprocessor">.Term</span>1 - <span class="hljs-keyword">sub</span><span class="hljs-preprocessor">.Term</span>2<span class="hljs-comment">;</span>
Sender<span class="hljs-preprocessor">.Tell</span>(new Answer(answer))<span class="hljs-comment">;</span>
})<span class="hljs-comment">;</span>
}
}</code></pre>
<p>Notice that we do not need to declare any fields, we can use locally declared variables.</p>
<h4 id="concurrency">Concurrency</h4>
<p>Suppose we send <code>Add(1,1)</code> and <code>Subtract(555,22)</code> to the actor. The actor start processing <code>Add(1, 1)</code> assign <code>answer=2</code> and then at the same time <code>Subtract(555,111)</code> calculates and assigns <code>answer=444</code>. When the handler of <code>Add(1,1)</code> creates the reply it will be <code>Answer(444)</code> which is clearly wrong.</p>
<p>How can we make sure this will not happen?</p>
<p>You don’t need to do anything. Akka.Net handles this for you. An actor can <strong>only process one message at the time</strong>. So if it has started processing <code>Add(1,1)</code> it will not start processing anything else until it has finished processing <code>Add(1,1)</code>.</p>
<h4 id="retrieve-state">Retrieve state</h4>
<p>So how can we get the latest answer from <code>CalculatorActor</code> now that <code>answer</code> is stored in a local variable inside the constructor? Can we make it a public field and then use that to access the value?</p>
<p>No, that will not help! Remember this line when we created the actor:</p>
<pre class="prettyprint"><code class="language-C# hljs perl">ActorRef calculator = <span class="hljs-keyword">system</span>.ActorOf<CalculatorActor>(<span class="hljs-string">"calculator"</span>);</code></pre>
<p><code>ActorOf</code> returns an <code>ActorRef</code>, not a <code>CalculatorActor</code> so we do not have access to public members on <code>CalculatorActor</code>. And that’s a good thing, as doing so would open up for sharing state.</p>
<p>Returning to one of the fundamentals of Actor based systems: </p>
<blockquote>
<p><strong>The only way to communicate with an actor is by messages</strong>.</p>
</blockquote>
<p>So we need to send it a message <code>GetLastAnswer</code> and let it reply with an <code>Answer</code> message.</p>
<p>First the new message. Since it doesn’t store any values, we create it as a singleton:</p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> GetLastAnswer
{
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> GetLastAnswer _instance=<span class="hljs-keyword">new</span> GetLastAnswer();
<span class="hljs-keyword">private</span> <span class="hljs-title">GetLastAnswer</span>() {}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> GetLastAnswer Instance { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _instance; } }
}</code></pre>
<p>Next we declare what <code>CalculatorActor</code> should do when it receives a <code>GetLastAnswer</code></p>
<pre class="prettyprint"><code class="language-C# hljs php">Receive<GetLastAnswer>(m => Sender.Tell(<span class="hljs-keyword">new</span> Answer(answer)));</code></pre>
<p>And then to test it, from <code>Main()</code> we ask for the last answer after the subtraction:</p>
<pre class="prettyprint"><code class="language-C# hljs avrasm">var answerSubtract = calculator<span class="hljs-preprocessor">.Ask</span><Answer>(new Subtract(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>))<span class="hljs-preprocessor">.Result</span><span class="hljs-comment">;</span>
Console<span class="hljs-preprocessor">.WriteLine</span>(<span class="hljs-string">"5 - 3 = "</span> + answerSubtract<span class="hljs-preprocessor">.Value</span>)<span class="hljs-comment">;</span>
var lastAnswer = calculator<span class="hljs-preprocessor">.Ask</span><Answer>(GetLastAnswer<span class="hljs-preprocessor">.Instance</span>)<span class="hljs-preprocessor">.Result</span><span class="hljs-comment">;</span>
Console<span class="hljs-preprocessor">.WriteLine</span>(<span class="hljs-string">"Last answer = "</span> + lastAnswer<span class="hljs-preprocessor">.Value</span>)<span class="hljs-comment">;</span></code></pre>
<p>If you run this you should see:</p>
<pre class="prettyprint"><code class=" hljs fix"><span class="hljs-attribute">1 + 2 </span>=<span class="hljs-string"> 3
5 - 3 = 2
Last answer = 2</span></code></pre>
<h3 id="code">Code</h3>
<p>One file containing all code: <br>
<a href="https://github.com/HCanber/akka.net-blog-examples/blob/master/02-calculator/CalculatorApp/Program.cs">https://github.com/HCanber/akka.net-blog-examples/blob/master/02-calculator/CalculatorApp/Program.cs</a></p>
<p>Entire project: <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/02-calculator">https://github.com/HCanber/akka.net-blog-examples/tree/master/02-calculator</a></p>
<p>All posts in this series: <a href="/p/akkanet.html">Tutorials for Akka.NET</a></p>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-45820343920799485072014-10-26T13:43:00.001+01:002014-10-26T15:40:08.365+01:00Getting Started with Akka.NET<p>Akka.NET is a toolkit and runtime for building highly concurrent, distributed, and fault tolerant event-driven applications on .NET and Mono. Instead of sharing state and managing concurrency ourselves Akka.NET handles this for us. We write the code in Actors, which has private state, runs in a single thread and interact with the outside via messages.</p>
<p>More information on Akka.NET can be found at <a href="http://akkadotnet.github.io/">http://akkadotnet.github.io/</a></p>
<p>Code for this post: <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/01-calculator">https://github.com/HCanber/akka.net-blog-examples/tree/master/01-calculator</a> <br>
All posts in this series: <a href="/p/akkanet.html">Tutorials for Akka.NET</a></p>
<blockquote>
<p><strong>Note!</strong> This post explains how to create a simple calculator in Akka.NET. It was written when Akka.NET was in version 0.7.0 and might not work for later versions</p>
</blockquote>
<h4 id="create-the-project">Create the project</h4>
<p>Start by creating a new <strong>Console App</strong> in Visual Studio. <br>
Install the nuget package <a href="https://www.nuget.org/packages/Akka"><strong>Akka</strong></a></p>
<pre class="prettyprint"><code class=" hljs mathematica">PM> <span class="hljs-keyword">Install</span>-Package Akka</code></pre>
<p>This is all that’s needed to start writing code for Akka.NET.</p>
<h4 id="create-message-classes">Create message classes</h4>
<p>The only way to communicate with an actor is by messages (simple <a href="http://en.wikipedia.org/wiki/Plain_Old_CLR_Object">poco</a> classes) . <br>
In this example we’ll send an <code>Add</code> message containing two integers to the calculator and we’ll get the answer as an <code>Answer</code> message.</p>
<div class="sequence-diagram"><svg height="265.46875" version="1.1" width="360.65625" xmlns="http://www.w3.org/2000/svg" style="overflow: hidden; position: relative; top: -0.553955078125px;"><desc style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Created with Raphaël 2.1.0</desc><defs style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><marker id="raphael-marker-endblock55" markerHeight="5" markerWidth="5" orient="auto" refX="2.5" refY="2.5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><use xlink:href="#raphael-marker-block" transform="rotate(180 2.5 2.5) scale(1,1)" stroke-width="1.0000" fill="#000" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></use></marker></defs><rect x="10" y="20" width="74.875" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="20" y="30" width="54.875" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="47.4375" y="39.546875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Program</tspan></text><rect x="10" y="206.375" width="74.875" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="20" y="216.375" width="54.875" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="47.4375" y="225.921875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Program</tspan></text><path fill="none" stroke="#000000" d="M47.4375,59.09375L47.4375,206.375" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><rect x="104.875" y="20" width="85" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="114.875" y="30" width="65" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="147.375" y="39.546875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Calculator</tspan></text><rect x="104.875" y="206.375" width="85" height="39.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="114.875" y="216.375" width="65" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="147.375" y="225.921875" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Calculator</tspan></text><path fill="none" stroke="#000000" d="M147.375,59.09375L147.375,206.375" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><rect x="69.609375" y="74.546875" width="55.59375" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="97.40625" y="84.09375" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Add(1, 2)</tspan></text><path fill="none" stroke="#000000" d="M47.4375,98.1875C47.4375,98.1875,122.12715246900916,98.1875,142.3677565316557,98.1875" stroke-width="2" marker-end="url(#raphael-marker-endblock55)" stroke-dasharray="0" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><rect x="167.375" y="118.1875" width="100.78125" height="29.09375" r="0" rx="0" ry="0" fill="none" stroke="#000000" stroke-width="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><rect x="172.375" y="123.1875" width="90.78125" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="217.765625" y="132.734375" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Calculates 1+2</tspan></text><rect x="66.09375" y="162.734375" width="62.625" height="19.09375" r="0" rx="0" ry="0" fill="#ffffff" stroke="none" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect><text x="97.40625" y="172.28125" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: 'Andale Mono', monospace;" font-size="16px" font-family="Andale Mono, monospace"><tspan dy="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Answer(3)</tspan></text><path fill="none" stroke="#000000" d="M147.375,186.375C147.375,186.375,72.68534753099084,186.375,52.44474346834431,186.375" stroke-width="2" marker-end="url(#raphael-marker-endblock55)" stroke-dasharray="0" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg></div>
<p>We define two classes to be our messages.</p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> Add
{
<span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">double</span> _term1;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">double</span> _term2;
<span class="hljs-keyword">public</span> <span class="hljs-title">Add</span>(<span class="hljs-keyword">double</span> term1, <span class="hljs-keyword">double</span> term2)
{
_term1 = term1;
_term2 = term2;
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> Term1 { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _term1; } }
<span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> Term2 { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _term2; } }
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> Answer
{
<span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">double</span> _value;
<span class="hljs-keyword">public</span> <span class="hljs-title">Answer</span>(<span class="hljs-keyword">double</span> <span class="hljs-keyword">value</span>)
{
_value = <span class="hljs-keyword">value</span>;
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> Value { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _value; } }
}</code></pre>
<h5 id="why-not-auto-properties">Why not Auto properties?</h5>
<p>All messages must be immutable, otherwise we’ve open up for sharing state. Readonly fields ensures the messages are immutable.</p>
<h4 id="the-calculator-actor">The Calculator actor</h4>
<p>Next is the <code>CalculatorActor</code>. We’ll start off with an empty class, and inherit from <a href="http://akkadotnet.github.io/wiki/ReceiveActor"><code>ReceiveActor</code></a>:</p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">using</span> Akka.Actor;
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> CalculatorActor : ReceiveActor
{
<span class="hljs-keyword">public</span> <span class="hljs-title">CalculatorActor</span>()
{
}
}</code></pre>
<p>That’s all we need for the <code>CalculatorActor</code> for now. We’ll come back to it later.</p>
<h4 id="create-the-actorsystem">Create the ActorSystem</h4>
<p>Actors are run in an <code>ActorSystem</code> and we need to create one.</p>
<pre class="prettyprint"><code class="language-C# hljs vala"><span class="hljs-keyword">using</span> Akka.Actor;
<span class="hljs-class"><span class="hljs-keyword">namespace</span> <span class="hljs-title">CalculatorApp</span>
{</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
{</span>
<span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> Main(<span class="hljs-keyword">string</span>[] args)
{
<span class="hljs-keyword">var</span> system = ActorSystem.Create(<span class="hljs-string">"calculator-system"</span>);
}
}
}</code></pre>
<h4 id="create-a-calculatoractor-instance">Create a CalculatorActor instance</h4>
<p>Now that we have a system, we can create a new instance of <code>CalculatorActor</code> using <code>system.ActorOf</code>. </p>
<pre class="prettyprint"><code class="language-C# hljs perl">var <span class="hljs-keyword">system</span> = ActorSystem.Create(<span class="hljs-string">"calculator-system"</span>);
ActorRef calculator = <span class="hljs-keyword">system</span>.ActorOf<CalculatorActor>(<span class="hljs-string">"calculator"</span>);</code></pre>
<p>In this example we’ve also given it the name <code>"calculator"</code>. This is optional, however since every actor must have a name, if you don’t give it a name it will be given a generated name. A good tip is to always name your actors . It will help when debugging, and when reading logs.</p>
<h4 id="send-a-message-to-the-calculator">Send a message to the calculator</h4>
<p>As you see above, <code>ActorOf</code> returns an <code>ActorRef</code> which acts as a proxy for the actual actor instance. This will allow us to communicate with the actor, without giving us access to any members exposed by the actor class. <br>
The next step is to send it an <code>Add</code> message. </p>
<pre class="prettyprint"><code class="language-C# hljs avrasm">ActorRef calculator = system<span class="hljs-preprocessor">.ActorOf</span><CalculatorActor>(<span class="hljs-string">"calculator"</span>)<span class="hljs-comment">;</span>
calculator<span class="hljs-preprocessor">.Tell</span>(new <span class="hljs-keyword">Add</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>))<span class="hljs-comment">;</span></code></pre>
<p>This will asynchronously send the <code>Add</code> message to the calculator actor. But we haven’t defined how the actor should deal with messages so let’s do that.</p>
<h4 id="handling-messages">Handling messages</h4>
<p>The <a href="http://akkadotnet.github.io/wiki/ReceiveActor"><code>ReceiveActor</code></a> allows us to declare what will happen when different messages are received, and we do that in the constructor:</p>
<pre class="prettyprint"><code class="language-C# hljs cs"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> CalculatorActor : ReceiveActor
{
<span class="hljs-keyword">public</span> <span class="hljs-title">CalculatorActor</span>()
{
Receive<Add>(add => Sender.Tell(<span class="hljs-keyword">new</span> Answer(add.Term1 + add.Term2)));
}
}</code></pre>
<p>The <code>Receive</code> statement says: <em>When the actor receives a message of type <code>Add</code> respond to the sender with an <code>Answer</code> message.</em></p>
<h4 id="receiving-responses">Receiving responses</h4>
<p>Next step is to receive the <code>Answer</code> and print it to the console. </p>
<p>One way we to interact with actors from the outside and to receive responses is to use <code>Ask</code> instead of <code>Tell</code>. It will return a <code>Task</code> on which we can await until a response is received. </p>
<p>So we switch to <code>Ask</code>, await an <code>Answer</code> (using the <code>Result</code> property which will block the current thread) and then print the result.</p>
<pre class="prettyprint"><code class="language-C# hljs avrasm">static void Main(string[] args)
{
var system = ActorSystem<span class="hljs-preprocessor">.Create</span>(<span class="hljs-string">"calculator-system"</span>)<span class="hljs-comment">;</span>
var calculator = system<span class="hljs-preprocessor">.ActorOf</span><CalculatorActor>(<span class="hljs-string">"calculator"</span>)<span class="hljs-comment">;</span>
var answer = calculator<span class="hljs-preprocessor">.Ask</span><Answer>(new <span class="hljs-keyword">Add</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>))<span class="hljs-preprocessor">.Result</span><span class="hljs-comment">;</span>
Console<span class="hljs-preprocessor">.WriteLine</span>(<span class="hljs-string">"Answer: "</span>+answer<span class="hljs-preprocessor">.Value</span>)<span class="hljs-comment">;</span>
Console<span class="hljs-preprocessor">.WriteLine</span>(<span class="hljs-string">"Press any key to exit"</span>)<span class="hljs-comment">;</span>
Console<span class="hljs-preprocessor">.ReadKey</span>()<span class="hljs-comment">;</span>
}</code></pre>
<p>That’s it. Go ahead and run it. You should see:</p>
<pre class="prettyprint"><code class=" hljs vbnet">Answer: <span class="hljs-number">3</span>
Press any <span class="hljs-keyword">key</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">exit</span></code></pre>
<h4 id="a-note-on-ask">A note on Ask</h4>
<p>While <code>Ask</code> is very useful when interacting with actors from the outside be aware of that there are performance implications of using <code>Ask</code> compared to using <code>Tell</code>. So always prefer <code>Tell</code> for performance, and only <code>Ask</code> if you must.</p>
<h4 id="code">Code</h4>
<p>One file containing all code: <br>
<a href="https://github.com/HCanber/akka.net-blog-examples/blob/master/01-calculator/CalculatorApp/Program.cs">https://github.com/HCanber/akka.net-blog-examples/blob/master/01-calculator/CalculatorApp/Program.cs</a></p>
<p>Entire project: <a href="https://github.com/HCanber/akka.net-blog-examples/tree/master/01-calculator">https://github.com/HCanber/akka.net-blog-examples/tree/master/01-calculator</a></p>
<h4 id="next">Next</h4>
<p>Next: <a href="/2014/10/handling-messages-and-state-with-akkanet.html">Handling messages and state</a> <br>
All posts in this series: <a href="/p/akkanet.html">Tutorials for Akka.NET</a></p>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-53959747327878906072014-01-10T14:06:00.001+01:002014-01-10T14:29:09.609+01:00Building Kafka 0.8.0 from sources on Windows<h2>Prerequisites – Java JDK</h2> <p>Although <a href="http://kafka.apache.org/">Kafka</a> is written in <a href="http://www.scala-lang.org/">Scala</a>, you do not need to install it. Only Java JDK is required.</p> <p>Download Java JDK: <br /><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">http://www.oracle.com/technetwork/java/javase/downloads/index.html</a></p> <p>Install it and make sure you update the PATH environment variable according to instructions: <br /><a href="http://docs.oracle.com/javase/7/docs/webnotes/install/windows/jdk-installation-windows.html">http://docs.oracle.com/javase/7/docs/webnotes/install/windows/jdk-installation-windows.html</a></p> <h2>Get the source</h2> <p>Do either the Clone-and-Checkout step or the Download step:</p> <ul> <li>Clone-and-Checkout <br />Execute: <pre>git clone <a href="http://git-wip-us.apache.org/repos/asf/kafka">http://git-wip-us.apache.org/repos/asf/kafka.git</a> kafka
cd kafka
git checkout -b 0.8 remotes/origin/0.8</pre>
</li>
<li>Download
<br />Download from <a href="https://github.com/apache/kafka">https://github.com/apache/kafka</a> ("Download Zip" button) and unpack to the folder kafka. Execute:
<pre>cd kafka</pre>
</li>
</ul>
<h2>Build</h2>
<p>Execute:</p>
<pre>.\sbt.bat update
.\sbt.bat package
.\sbt.bat assembly-package-dependency</pre>
<h2>Update the bat files</h2>
<p>Unfortunately the bat files for Kafka 0.8.0 are full of errors, so in order to start Zookeeper and Kafka they must be replaced. See <a href="http://hocke.blogspot.com/2014/01/kafka-080-on-windows.html#update-bat">Step 1, Update the bat files</a>.</p>
<h2>Update config for Windows</h2>
<p>Update the config files according to <a href="http://hocke.blogspot.com/2014/01/kafka-080-on-windows.html#update-config">Step 1, Update Config</a>.</p>
<h2>Run</h2>
<p>To run, see <a href="http://hocke.blogspot.com/2014/01/kafka-080-on-windows.html#step-2">Step 2, Start the server</a>.</p>
<p> </p>
<p>See <a href="http://hocke.blogspot.com/2014/01/kafka-080-on-windows.html">Running Kafka 0.8.0 on Windows</a> for more info on how to set up and run Kafka using the binary distribution.</p> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com1tag:blogger.com,1999:blog-4681772286990545567.post-62805971103110124382014-01-10T10:01:00.001+01:002014-01-10T14:11:36.172+01:00Kafka 0.8.0 on Windows<p>Getting Kafka 0.8.0 running on Windows isn’t straight forward if you follow the <a href="http://kafka.apache.org/documentation.html#quickstart">instructions</a>. They are somewhat misleading, and the bat files are old. But with correct instructions and updated bat files it’s easy and can be done under 10 minutes. Some say you need Cygwin in order to run Kafka. This is not true. Only Server JRE is required.</p> <h2>Step 0. Prerequisite – Java SE Server JRE</h2> <p>You need Java SE Server JRE in order to run Kafka. If you have JDK installed, you already have Server JRE installed.</p> <ol> <li>Download Java SE Server JRE <br /><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">http://www.oracle.com/technetwork/java/javase/downloads/index.html</a> <br />For me Chrome changed the extension. If that happens change it back to .tar.gz in order to unpack it. </li> <li>Unpack it to a folder, for example c:\JreServer <br />Update the system environment variable PATH to include C:\JreServer\jre\bin (Control Panel and search for environment variable). </li> </ol> <h2 id="step-1">Step 1. Download Kafka</h2> <ol> <li>Download the binaries for Kafka from <a title="http://kafka.apache.org/downloads.html" href="http://kafka.apache.org/downloads.html">http://kafka.apache.org/downloads.html</a> </li> <li>Unzip to a folder, for example c:\kafka </li> </ol> <h5 id="update-bat">Update the bat files</h5> <p>Unfortunately the bat files for Kafka 0.8.0 are full of errors, so in order to start Zookeeper and Kafka they must be replaced.</p> <ol> <li>Download updated windows bat files from <a href="https://github.com/HCanber/kafka/releases"><font color="#0066cc">https://github.com/HCanber/kafka/releases</font></a> </li> <li>Unzip and copy them into c:\kafka\bin\windows (overwrite the files already there) </li> </ol> <h5 id="update-config">Update Config</h5> <p>The config files need to be updated.</p> <ol> <li>Open config\server.properties and locate <code>log.dirs=/tmp/kafka-logs</code>. If you keep the default it will result in an error later on. Set it to a full path without . or .. in it and with <strong>forward</strong> slashes. Example: <pre>log.dirs=c:/kafka/kafka-logs</pre>
</li>
<li>This step is optional but you might want to set the data directory for Zookeeper as well. Open config\zookeeper.properties and locate <code>dataDir=/tmp/zookeeper</code>. Example:
<pre>dataDir=c:/kafka/zookeeper-data</pre>
</li>
</ol>
<h2 id="step-2">Step 2. Start the server</h2>
<p><b>Note!</b> Before executing the commands below you need to change directory to the folder where you unzipped Kafka: </p>
<pre>cd c:\kafka</pre>
<ol>
<li>Start Zookeeper in a Command Prompt or PowerShell Console.
<pre>.\bin\windows\zookeeper-server-start.bat .\config\zookeeper.properties</pre>
</li>
<li>Start Kafka in another Command Prompt or PowerShell Console.
<pre>.\bin\windows\kafka-server-start.bat .\config\server.properties</pre>
</li>
</ol>
<h2 id="step-3">Step 3. Create a topic</h2>
<ol>
<li>Create a topic.
<pre>.\bin\windows\kafka-create-topic.bat --zookeeper localhost:2181 --replica 1 --partition 1 --topic test</pre>
</li>
<li>List topics.
<pre>.\bin\windows\kafka-list-topic.bat --zookeeper localhost:2181</pre>
</li>
</ol>
<h2 id="step-4">Step 4. Send some messages</h2>
<ol>
<li>Start Console Producer
<pre>.\bin\windows\kafka-console-producer.bat --broker-list localhost:9092 --topic test</pre>
</li>
<li>Write some messages
<pre>This is a message
This is another message</pre>
</li>
</ol>
<h2 id="step-5">Step 5. Start a consumer</h2>
<ol>
<li>Start Console Consumer
<pre>.\bin\windows\kafka-console-consumer.bat --zookeeper localhost:2181 --topic test --from-beginning</pre>
</li>
</ol>
<p> </p>
<h2>Building from sources</h2>
<p>See <a href="http://hocke.blogspot.se/2014/01/building-kafka-080-from-sources-on.html">Building Kafka 0.8.0 from sources on Windows</a></p> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com8tag:blogger.com,1999:blog-4681772286990545567.post-40469307609490252322013-01-30T22:04:00.001+01:002013-01-31T10:45:59.593+01:00Nancy and Owin<p>This is a short post on how to run <a href="http://nancyfx.org/">NancyFX</a> in an <a href="http://owin.org/">Owin</a> pipeline on a <a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx">HttpListener</a> Host.</p><div style="border:solid 1px #777; padding:1em;margin-bottom:1em;"><h2>Update</h2><p>David Fowler (<a href="https://twitter.com/davidfowl">@davidfowl</a>), and an anonymous commenter, pointed out there was a better way to set up Owin hosting. The code has been updated. <br />
</p></div><p>Note, before we start. Since HttpListener might require permissions, the easiest way round this is running as an administrator, or starting VS2012 as administrator. You shouldn’t be doing this in production. <a href="http://msdn.microsoft.com/en-us/library/ms733768.aspx">Configuring HTTP and HTTPS on MSDN</a>.</p><h2>Create a Console App</h2><p>Create a Console App and install the following packages in the Package Manager Console. Note that prerelease nuget packages are used.</p><pre>Install-Package Microsoft.Owin.Host.HttpListener -Pre
Install-Package Microsoft.Owin.Hosting -pre
Install-Package Nancy.Hosting.Owin</pre><p>These packages will also be installed when the packages above are installed:</p><p>Owin, Nancy</p><h3>The Code</h3><p>First we need a Nancy Module:</p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> SampleModule : NancyModule
{
<span class="kwrd">public</span> SampleModule()
{
Get[<span class="str">"/"</span>] = _ => <span class="str">"Hello World!"</span>;
}
}</pre><p>Then we need to configure the Owin application to run Nancy.</p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> Startup
{
<span class="kwrd">public</span> <span class="kwrd">void</span> Configuration(IAppBuilder app)
{ <span class="rem">//Uses an extension method that adds Nancy at the end of an Owin pipeline</span>
app.RunNancy();
}
}</pre><p>The extension method used to configure the app:</p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> NancyOwinAppBuilderExtensions
{
<span class="kwrd">public</span> <span class="kwrd">static</span> IAppBuilder RunNancy(<span class="kwrd">this</span> IAppBuilder builder)
{
<span class="kwrd">return</span> RunNancy(builder, <span class="kwrd">new</span> DefaultNancyBootstrapper());
}
<span class="kwrd">public</span> <span class="kwrd">static</span> IAppBuilder RunNancy(<span class="kwrd">this</span> IAppBuilder builder, INancyBootstrapper bootstrapper)
{
<span class="kwrd">var</span> nancyOwinHost = <span class="kwrd">new</span> NancyOwinHost(bootstrapper);
<span class="kwrd">return</span> RunNancy(builder, nancyOwinHost);
}
<span class="kwrd">public</span> <span class="kwrd">static</span> IAppBuilder RunNancy(<span class="kwrd">this</span> IAppBuilder builder, NancyOwinHost host)
{
<span class="kwrd">return</span> RunApp(builder, host.ProcessRequest);
}
<span class="kwrd">private</span> <span class="kwrd">static</span> IAppBuilder RunApp(IAppBuilder builder, Func<IDictionary<<span class="kwrd">string</span>, <span class="kwrd">object</span>>, Task> app)
{
<span class="kwrd">return</span> UseFunc(builder, next => app);
}
<span class="kwrd">private</span> <span class="kwrd">static</span> IAppBuilder UseFunc(IAppBuilder builder, Func<Func<IDictionary<<span class="kwrd">string</span>, <span class="kwrd">object</span>>, Task>, Func<IDictionary<<span class="kwrd">string</span>, <span class="kwrd">object</span>>, Task>> middleware)
{
<span class="kwrd">return</span> builder.Use((<span class="kwrd">object</span>)middleware, <span class="kwrd">new</span> <span class="kwrd">object</span>[0]);
}
}</pre><p>Lastly we put everything together and starts the Owin Server:</p><pre class="csharpcode"><span class="kwrd">class</span> Program
{
<span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)
{
<span class="kwrd">var</span> url = <span class="str">"http://+:8080"</span>;
<span class="kwrd">using</span> (WebApplication.Start<Startup>(url))
{
Console.WriteLine(<span class="str">"Running on http://localhost:8080"</span>, url);
Console.WriteLine(<span class="str">"Press enter to exit"</span>);
Console.ReadLine();
}
}
}</pre><p>That’s it. Hit F5 to run it. Visit <a href="http://localhost:8080/">http://localhost:8080/</a> in a browser.</p><h3>Package versions</h3><p>The following packages were used in the code.</p><pre>Microsoft.Owin.Host.HttpListener version=0.18.0-alpha
Microsoft.Owin.Hosting version=0.18.0-alpha
Nancy version=0.15.3
Nancy.Hosting.Owin version=0.15.3
Owin version=1.0</pre><h2>Download code</h2><p><a title="https://gist.github.com/4676779" href="https://gist.github.com/4676779">https://gist.github.com/4676779</a></p>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com2tag:blogger.com,1999:blog-4681772286990545567.post-26430170051059373562011-09-23T14:15:00.001+02:002011-09-23T14:15:43.619+02:00Using the Topshelf Shelving Bootstrapper in a Console App<p><strong>Note!</strong> This was written for Topshelf 2.2.2.0 and things might have changed in newer versions.</p> <h2>Topshelf</h2> <p>Topshelf (<a href="http://topshelf-project.com/"><font color="#0066cc">http://topshelf-project.com</font></a>) is a framework for building Windows services. The service can either be standalone or one that is hosted by Topshelf. The latter style is called <a href="http://topshelf-project.com/documentation/shelving/">shelving</a> (and the service you write is called a shelf) and it enables xcopy deploy of your service, instead of stop service, uninstall, copy, install, start.</p> <h2>Debugging a shelf</h2> <p>The problem with using the shelving style for your service is debugging. The documentation explains how to do it (<a href="http://topshelf-project.com/debugging-a-topshelf-shelf/">http://topshelf-project.com/debugging-a-topshelf-shelf/</a>), but it’s not that neat as it involves modifying where your build outputs the dlls.</p> <p>An easier way, at least for me, would be to debug the shelf service by starting it from a console app, i.e. as a standalone service, without any need to modify where the output from the build goes. Ideally the console app would be as simple as possible, just reusing the code from the shelf. </p> <p>A shelf service is initiated and configured by a bootstrapper (a class that inherits the interface <code>Bootstrapper<T></code>) but unfortunately, if you compare the configuration for a <a href="http://topshelf-project.com/documentation/getting-started/">standalone service</a> with the <a href="http://topshelf-project.com/documentation/shelving/">shelf bootstrapper</a>, they are not configured the same way, so reusing the configuration from the shelf bootstrapper in a standalone service seems not possible, but it’s actually quite easy.</p> <h2>Reuse the bootstrapper</h2> <p>Instead of implementing <code>Bootstrapper<T></code> derive from this class instead:</p> <!-- code formatted by http://manoli.net/csharpformat/ --> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">abstract</span> <span class="kwrd">class</span> BootstrapperBase<T> : Bootstrapper<T> <span class="kwrd">where</span> T : <span class="kwrd">class</span>
{
<span class="kwrd">void</span> <span style="color: #2b91af">Bootstrapper</span><T>.InitializeHostedService(IServiceConfigurator<T> cfg)
{
InitializeHostedService(cfg);
}
<span class="kwrd">public</span> <span class="kwrd">abstract</span> <span class="kwrd">void</span> InitializeHostedService(ServiceConfigurator<T> cfg);
}</pre>
<p>Instead of implementing
<br /><code><span style="color: blue">void</span> InitializeHostedService(IServiceConfigurator<T><t> cfg)</code>
<br />you implement
<br /><font face="Courier New"><span style="color: blue">void</span> InitializeHostedService(ServiceConfigurator<T><t> cfg)</font></p>
<p>The bootstrapper in the example at <a href="http://topshelf-project.com/documentation/shelving/"><font color="#0066cc">http://topshelf-project.com/documentation/shelving/</font></a> becomes (changes are highlighted)</p>
<!-- code formatted by http://manoli.net/csharpformat/ -->
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> AShelvedClockBootstrapper :
<span style="background: #ff0">BootstrapperBase</span><TheClock>
{
<span class="kwrd">public</span> <span style="background: #ff0" class="kwrd">override</span> <span class="kwrd">void</span> InitializeHostedService(<span style="background: #ff0">ServiceConfigurator</span><TheClock> cfg)
{
cfg.<span style="background: #ff0">ConstructUsing</span>(n => <span class="kwrd">new</span> TheClock());
cfg.WhenStarted(s =>
{
XmlConfigurator.Configure(<span class="kwrd">new</span> FileInfo(Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
<span class="str">"clock.log4net.config"</span>)));
s.Start();
});
cfg.WhenStopped(s => s.Stop());
}
}</pre>
<p>In the console app you start the service like this:</p>
<pre class="csharpcode"><span style="color: blue">static</span> <span style="color: blue">void</span> Main(<span style="color: blue">string</span>[] args)
{
<span style="color: #2b91af">XmlConfigurator</span>.ConfigureAndWatch(<span style="color: blue">new</span> <span style="color: #2b91af">FileInfo</span>(<span style="color: #a31515">".\\log4net.config"</span>));
<span style="color: #2b91af">HostFactory</span>.Run(x =>
{
x.Service<<span style="color: #2b91af">TheClock</span>>(<br />        s => <span style="color: blue">new</span> <span style="color: #2b91af">AShelvedClockBootstrapper</span>().InitializeHostedService(s));
x.RunAsLocalSystem();   x.SetServiceName(<span style="color: #a31515">"TheClock"</span>);
});
}</pre> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-60737578483078737162011-08-31T20:59:00.002+02:002011-08-31T21:08:26.795+02:00“Hello World” with OWIN (on Kayak)A link to all code can be found at <a href="#gist-1184386">the end of this post</a>.
<p>When I started implementing an <a href="http://owin.org/">OWIN</a> compatible web framework I couldn’t find any examples on how to get started with OWIN. <a href="http://jclaes.blogspot.com/2011/01/hello-world-with-kayak-and-owin.html">Jef Claes</a> has an example but this seems to be for an older draft of OWIN. So this post is about how to create a really simple OWIN web application in C#. It’s inspired by <a href="http://jclaes.blogspot.com/2011/01/hello-world-with-kayak-and-owin.html">Jef Claes</a> code and uses code from <a href="http://bvanderveen.com/a/gate-0.1.0/">Benjamin van der Veen´s example</a>.</p> <p> </p> <p>Please Note!
This post was written when OWIN was Draft 1.0, using Kayak 0.7.2 and Gate 0.1.4. Things might have changed since this post.</p> <p> </p> <h2>Set up the project</h2> <p>Start by creating a C# Console App.</p> <p>Install the <a href="http://nuget.codeplex.com/wikipage?title=Getting%20Started">NuGet</a> package <a href="http://nuget.org/list/packages/gate.kayak">Gate.Kayak</a>. This will install the these packages too: <a href="http://nuget.org/List/Packages/Gate">Gate</a> & <a href="http://nuget.org/list/packages/kayak">Kayak</a>.</p> <p><a href="http://kayakhttp.com/">Kayak</a> is is an asynchronous HTTP server written in C#.
<a href="http://nuget.org/list/packages/gate.kayak">Gate.Kayak</a> brings OWIN support to Kayak. If you want to host your OWIN app in another environment use another gate like <a href="http://nuget.org/List/Packages/Gate.AspNet">Gate.AspNet</a> or <a href="http://nuget.org/List/Packages/Gate.Wcf">Gate.Wcf</a>.</p> <h2>Create the Kayak Web Server</h2> <p>In order to set up a Kayak web server, we need to tell Kayak three things: What endpoint to listen to; how to handle exceptions and shut downs; and how to handle the incoming requests.</p> <h3>Main() – Configuring and Starting the Server</h3> <p>In this example the <code>Main</code> method of the Console App configures the Kayak server and starts it.</p> <pre class="csharpcode"><span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)
{
<span class="rem">//Create the endpoint for incoming requests to Kayak </span>
var kayakEndPoint = <span class="kwrd">new</span> IPEndPoint(IPAddress.Any, 5500);
Console.WriteLine(<span class="str">"Listening on "</span> + kayakEndPoint);
<span class="rem">//Start Kayak and call the method Startup.Configuration when starting
</span><span class="rem"> //Let SchedulerDelegate handle exceptions and shut downs</span>
KayakGate.Start(<span class="kwrd">new</span> SchedulerDelegate(), kayakEndPoint, Startup.Configuration);
}</pre>
<p>An endpoint on port 5500 is created. When Kayak is starting it will configure itself by calling the <code>Startup.Configuration</code> method (more on this below), and when stopped, or when an exception is thrown, <code>SchedulerDelegate</code> handles this.</p>
<h3>SchedulerDelegate </h3>
<p>The methods in <code>SchedulerDelegate</code> class is called when exceptions during Kayak´s event loop occurs and when Kayak is being stopped. We’ll just write messages to the Console.</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> SchedulerDelegate : ISchedulerDelegate
{
<span class="kwrd">public</span> <span class="kwrd">void</span> OnException(IScheduler scheduler, Exception e)
{
<span class="rem">// called whenever an exception occurs on Kayak's event loop.</span>
<span class="rem">// this is good place for logging. here's a start:</span>
Console.WriteLine(<span class="str">"Exception on scheduler"</span>);
Console.Out.WriteStackTrace(e);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> OnStop(IScheduler scheduler)
{
<span class="rem">// called when Kayak's run loop is about to exit.</span>
<span class="rem">// this is a good place for doing clean-up or other chores.</span>
Console.WriteLine(<span class="str">"Scheduler is stopping."</span>);
}
}</pre>
<h3>Startup.Configuration</h3>
<p>Next we need to tell Kayak what to do with incoming requests. The method <code>Startup.Configuration</code> is responsible for that and it will be called when Kayak is starting. In this example, we specified it explicitly in the <code>Main</code> method, but if you were to host the OWIN application on Asp.Net using <a href="http://nuget.org/List/Packages/Gate.AspNet">Gate.AspNet</a> this method will automatically be found and invoked (it’s a convention in Kayak). So creating class with the name <code>Startup</code> with a static method <code>Configuration</code> makes your application more easily portable to other Gate hosts.</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> Startup
{
<span class="rem">// called automatically when Kayak starts up.</span>
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Configuration(IAppBuilder builder)
{
<span class="rem">// we'll create a very simple pipeline:</span>
var app = <span class="kwrd">new</span> HelloWorldOwinApp();
builder.Run(Delegates.ToDelegate(app.ProcessRequest));
}
}</pre>
<p>First our OWIN application is instantiated and then Kayak is told to to let the app´s <code>ProcessRequest</code> method handle all incoming requests.</p>
<h2>HelloWorldOwinApp</h2>
<p>The primary interface in OWIN is the application delegate. An application delegate takes three parameters: an environment dictionary, a response callback, and an error callback. The <code>HelloWorldOwinApp</code> class exposes the method <code>ProcessRequest</code> that has the same signature as the application delegate specified in <a href="http://owin.org/spec.html#ApplicationDelegate">OWIN Draft 1.0</a> and this is where all the fun happens. </p>
<p>If the requested resource, i.e. the path, is the root, “/”, we return a Hello World html page. Otherwise a 404 page is returned.</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> HelloWorldOwinApp
{
<span class="kwrd">public</span> <span class="kwrd">void</span> ProcessRequest(
IDictionary<<span class="kwrd">string</span>, <span class="kwrd">object</span>> environment,
Action<<span class="kwrd">string</span>, IDictionary<<span class="kwrd">string</span>, <span class="kwrd">string</span>>,
Func<Func<ArraySegment<<span class="kwrd">byte</span>>, Action, <span class="kwrd">bool</span>>,
Action<Exception>, Action, Action>> responseCallBack,
Action<Exception> errorCallback)
{
var path = environment[<span class="str">"owin.RequestPath"</span>] <span class="kwrd">as</span> <span class="kwrd">string</span>;
var responseHeaders = <span class="kwrd">new</span> Dictionary<<span class="kwrd">string</span>, <span class="kwrd">string</span>>();
ArraySegment<<span class="kwrd">byte</span>> responseBody;
<span class="kwrd">string</span> responseStatus;
<span class="kwrd">if</span> (path == <span class="str">"/"</span>)
{
responseStatus = <span class="str">"200 OK"</span>;
responseHeaders.Add(<span class="str">"Content-Type"</span>, <span class="str">"text/html"</span>);
responseBody = <span class="kwrd">new</span> ArraySegment<<span class="kwrd">byte</span>>(Encoding.UTF8.GetBytes((
<span class="str">"<!doctype html><html><head><meta charset=\"utf-8\">"</span> +
<span class="str">"<title>Hello World</title></head>"</span> +
<span class="str">"<body><strong>Hello world</strong></body>"</span> +
<span class="str">"</html>"</span>)));
}
<span class="kwrd">else</span>
{
responseStatus = <span class="str">"404 Not Found"</span>;
responseHeaders.Add(<span class="str">"Content-Type"</span>, <span class="str">"text/html"</span>);
responseBody = <span class="kwrd">new</span> ArraySegment<<span class="kwrd">byte</span>>(Encoding.UTF8.GetBytes((
<span class="str">"<!doctype html><html><head><meta charset=\"utf-8\">"</span> +
<span class="str">"<title>404 Not Found</title></head>"</span> +
<span class="str">"<body>The resource cannot be found.</body>"</span> +
<span class="str">"</html>"</span>)));
}
responseCallBack(
responseStatus,
responseHeaders,
(next, error, complete) => // This is the Body Delegate
{
next(responseBody, <span class="kwrd">null</span>);
complete();
<span class="kwrd">return</span> () => { };
});
}
}</pre>
<p>The signature is hideous. The people behind OWIN are well aware of this, and considered interfaces in an assembly that all had to implement, but, thankfully, decided to go with using Funcs and Actions instead. This means that there is no OWIN.dll you have to reference, and therefor no versioning conflicts can occur.</p>
<p>Except from the signature, this method is pretty straightforward. We get the relative path from the environment dictionary. If it’s “/” we return a Hello World html page. Otherwise a 404 page is returned.</p>
<p>Returning the resource is a bit special. Instead of just returning some kind of object with headers, status and body content the <code>responseCallBack</code> is invoked. This is necessary for everything to be asynchronous. The callback has as three arguments: the response status; response headers; and a delegate (the next-error-complete-delegate) for retrieving the body content. </p>
<p>The delegate is called the Body Delegate and it is invoked by the host whenever it is ready to receive the body content. The signature of the delegate makes it possible to return chunks of the body. But to keep it simple we will return everything in one chunk, and that is what the <code>next(responseBody, null)</code> call does. <code>responseBody</code> is an ArraySegment (basically a byte array with information about which part of the array the consumer should use).</p>
<p>For simple applications, like this, you don’t have to understand how the Body delegate is intended to be used. Just copy-paste this example, and add the content to <code>responseBody</code>.</p>
<h2>Say Hello!</h2>
<p>Start the console app. In a browser navigate to <a href="http://localhost:5500/">http://localhost:5500</a>. You should see a page with “Hello World” in bold. Now go to <a href="http://localhost:5500/NotThere">http://localhost:5500/NotThere</a> and you’ll get a 404 page.</p>
<p>That’s it. Now you have everything you need to create a OWIN web application.</p>
<h2>Code</h2>
<p id="gist-1184386">The code can be found on github gist. <a href="https://gist.github.com/1184386">Show all code</a>.</p> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-59527081486324398022011-03-09T15:42:00.001+01:002011-03-09T15:42:00.190+01:00An extension method for creating a strict mock in FakeItEasy<p>The <a href="http://code.google.com/p/fakeiteasy/">FakeItEasy</a> framework prefers that you don’t create strict mocks, but whenever you need one this extension method might come in handy.</p> <!-- code formatted by http://manoli.net/csharpformat/ --> <pre class="csharpcode"><span class="rem">/// <summary></span><span class="rem">Creates a strict mock of type <typeparamref name="T"/>.</span><span class="rem"></summary></span>
<span class="rem">/// <typeparam name="T">The type of the object to fake.</typeparam></span>
<span class="rem">/// <returns>A FakeItEasy fake configured to behave as a strict mock.</returns></span>
<span class="kwrd">public</span> <span class="kwrd">static</span> T Mock<T>()
{
var fake = A.Fake<T>();
Any.CallTo(fake).Throws(<span class="kwrd">new</span> Exception(<span class="kwrd">string</span>.Format(<span class="str">"An unexpected method was called on the fake object {0}."</span>, <span class="kwrd">typeof</span>(T))));
<span class="kwrd">return</span> fake;
}</pre>
<p>To create a strict mock:</p>
<pre class="csharpcode">var foo = AStrict.Mock<IFoo>();</pre>
<p>After you have configured your mock in this fashion you can configure any "allowed" calls as usual, for example:</p>
<pre class="csharpcode">A.CallTo(() => foo.Bar()).Returns(<span class="str">"bar"</span>);</pre>
<p> </p>
<p>Example and code based on: <a href="http://code.google.com/p/fakeiteasy/wiki/StrictMocks">http://code.google.com/p/fakeiteasy/wiki/StrictMocks</a></p> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-8229421862082894832011-02-13T21:57:00.001+01:002011-02-13T21:57:15.836+01:00Set Custom Tool in the Item Template file<p>Documentation for setting the Custom Tool property for a project item created from an item template is not exactly easily found. </p> <p>There are two things you need in the .vstemplate-file (I’ll assume you know how to <a title="How to: Create Item Templates in VS 2010 on MSDN" href="http://msdn.microsoft.com/en-us/library/tsyyf0yh.aspx">create item templates</a>). First you need to include a WizardExtension-node and next you need to specify a CustomTool attribute on the ProjectItem. Both are marked in yellow below.</p> <!-- code formatted by http://manoli.net/csharpformat/ --><style type="text/css">
.csharpcode .important { background-color: #ff9; }</style> <pre class="csharpcode"><span class="kwrd"><</span><span class="html">VSTemplate</span> <span class="attr">Version</span><span class="kwrd">="3.0.0"</span> <span class="attr">xmlns</span><span class="kwrd">="http://schemas.microsoft.com/developer/vstemplate/2005"</span> <span class="attr">Type</span><span class="kwrd">="Item"</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">TemplateData</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">DefaultName</span><span class="kwrd">></span>MyFile.txt<span class="kwrd"></</span><span class="html">DefaultName</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">Name</span><span class="kwrd">></span>My File<span class="kwrd"></</span><span class="html">Name</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">Description</span><span class="kwrd">></span>My File<span class="kwrd"></</span><span class="html">Description</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">ProjectType</span><span class="kwrd">></span>CSharp<span class="kwrd"></</span><span class="html">ProjectType</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">SortOrder</span><span class="kwrd">></span>1<span class="kwrd"></</span><span class="html">SortOrder</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">Icon</span><span class="kwrd">></span>__TemplateIcon.ico<span class="kwrd"></</span><span class="html">Icon</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">TemplateData</span><span class="kwrd">></span>
<div class="important"> <span class="kwrd"><</span><span class="html">WizardExtension</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">Assembly</span><span class="kwrd">></span>Microsoft.VSDesigner, Version=10.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a<span class="kwrd"></</span><span class="html">Assembly</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">FullClassName</span><span class="kwrd">></span>Microsoft.VSDesigner.ProjectWizard.ItemPropertyWizard<span class="kwrd"></</span><span class="html">FullClassName</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">WizardExtension</span><span class="kwrd">></span></div>
<span class="kwrd"><</span><span class="html">TemplateContent</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">References</span> <span class="kwrd">/></span>
<span class="kwrd"><</span><span class="html">ProjectItem</span> <span class="attr">SubType</span><span class="kwrd">="Code"</span> <span class="attr">TargetFileName</span><span class="kwrd">="$fileinputname$.txt"</span> <span class="attr">ReplaceParameters</span><span class="kwrd">="false"</span> <span class="important"><span class="attr">CustomTool</span><span class="kwrd">="MyCustomTool"</span></span><span class="kwrd">></span>MyFile.txt<span class="kwrd"></</span><span class="html">ProjectItem</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">TemplateContent</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">VSTemplate</span><span class="kwrd">></span></pre> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com1tag:blogger.com,1999:blog-4681772286990545567.post-27953052618195355882010-12-30T15:34:00.001+01:002010-12-30T15:34:52.629+01:00How to register for a WP7Dev account<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:a6e2c67d-260c-44ca-b570-4d70f8f157b9" class="wlWriterEditableSmartContent">Technorati Tags: <a href="http://technorati.com/tags/Windows+Phone+7" rel="tag">Windows Phone 7</a>,<a href="http://technorati.com/tags/WP7" rel="tag">WP7</a>,<a href="http://technorati.com/tags/%23WP7" rel="tag">#WP7</a>,<a href="http://technorati.com/tags/%23WP7Dev" rel="tag">#WP7Dev</a></div> <p>Want to create applications for the Windows Phone 7 (WP7)? You need to register in order to be able to do that, even if you you only want to deploy the application to your own phone and not to the AppHub. Since I haven’t seen any description of the process I wrote down what I had to to. Note that I live in Sweden and the process might vary by countries, but most likely this is what you have to go thru as an individual non-US developer.</p> <h2>1. Register and pay</h2> <p>Register at <a title="http://windowsphone.create.msdn.com/AppSubmission" href="http://windowsphone.create.msdn.com/AppSubmission">http://windowsphone.create.msdn.com/AppSubmission</a> </p> <p>Make sure: </p> <ul> <li>you enter the correct information since it might be hard to change it later: <a href="http://forums.create.msdn.com/forums/t/69335.aspx">http://forums.create.msdn.com/forums/t/69335.aspx</a> </li> <li>you enter the display name you want since it cannot be changed. At all. Ever: <a href="http://forums.create.msdn.com/forums/t/68212.aspx">http://forums.create.msdn.com/forums/t/68212.aspx</a> </li> </ul> <p>Beware that the fee is said to be $99 USD but in reality this might differ, especially if you´re outside US. In Sweden it will cost you €99. Also beware that the amount you’re accepting, which for me was 919 SEK (€99) is not the amount you’ll be charged. To that a tax of 15% is added, so I was charged 1057 SEK ($150). I’m not sure if it’s legal to ask for acceptance of one amount and then charge another. But, according to Shaun Taulbee, Microsoft: </p> <blockquote> <p><em>“Price adjustments are coming, and I'm told refunds will be automatically applied for those who registered since October” <br /></em><a href="http://forums.create.msdn.com/forums/p/67701/423198.aspx#423198">http://forums.create.msdn.com/forums/p/67701/423198.aspx#423198</a></p> </blockquote> <h2>2. Email: Confirm the email address! /Microsoft</h2> <p>After registering and paying an email will be sent to the email you provided during registration (which might differ from the Live account) in order to confirm the email address. It contains a link that needs to be opened. </p> <h2>3. Email: Approve request! /GeoTrust</h2> <p>Now you should receive an email form GeoTrust. If you haven’t received it within 24 hrs (remember to check your Spam/Junk email folder first) you should contact GeoTrust directly, according to the FAQ: <a href="http://create.msdn.com/en-US/home/faq/windows_phone_7#wp7faq10">http://create.msdn.com/en-US/home/faq/windows_phone_7#wp7faq10</a> <br />For me the email came instantly. </p> <p>Open the link to GeoTrust that was sent to you in the email an approve the order. <br />”Your order has been successfully approved and your authenticated identity validation status will be reflected on the Windows Phone 7 AppHub within two business days.” </p> <h2>4. Email: Send identification confirmation! /GeoTrust</h2> <p>You just have to wait for the next email from GeoTrust:</p> <blockquote> <p><em>“In order for GeoTrust to confirm your information in terms of Microsoft's requirements, GeoTrust must receive a copy of your valid government issued photo identification (for example: a passport or driver's license), attached to the Identification Confirmation Letter below.”</em></p> </blockquote> <p>You can fax them the information or send it by email, which is what I did: Print out a copy of the letter. Fill the fields at the bottom (all the info is on your passport). Sign it. Scan the letter with your passport at the designated position. Email GeoTrust with the scanned letter as an attachment.</p> <h2>5. Email: Your email was received. /GeoTrust</h2> <p>After a while you’ll receive an email acknowledging the receipt of your Identification Confirmation email.</p> <blockquote> <p><em>“The verification process will be completed within 1-2 business days. If you have any questions, please contact us.”</em></p> </blockquote> <p></p> <h2>6. “Welcome to the Windows Phone Marketplace developer program”</h2> <p>The next email should be from Microsoft welcoming you to the program. For me, it took 6 hours to receive this email.</p> <p>You’re done…. Sort of…. In order to receive payment for your apps you’ll need to do more, but I’ll stop here.</p> <h2>Shortcutting the process </h2> <p>“Wow, that’s many steps and a whole lot of waiting”, you may think. Yeah, it is. But there is a way to speed up the process which worked for me and a <a title="Anders Ljusberg" href="http://coding-insomnia.com/">friend of mine</a>. Step 1-3 runs smoothly (no human interaction I would guess), but instead of waiting up to 2 days for step 4 and 5 you can contact GeoTrust via their chat: <a href="https://www.geotrust.com/support/chat/order-processing.html">https://www.geotrust.com/support/chat/order-processing.html</a></p> <p>Instead of waiting for step 4, ask them for status of your order. <br />After sending the email in step 4, ask them to check they have received the email, and that it contains the correct information.</p> <p>For me the steps 1-6 took 2.5 days.</p> <h2>Register the phone</h2> <p>Connect the phone to your computer. Make sure Zune starts. Start the “Windows Phone Developer Registration” program (from the start menu) and enter your Live ID and Password and click Register. Make sure the phone is not locked. For me it took some attempts. I had to restart the phone and then clicking retry a few times.</p> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-25153859036046692642010-09-02T17:25:00.001+02:002010-09-02T17:25:04.604+02:00How to get the Single File Generator sample running<p>I’ve started developing a CustomTool for Visual Studio 2010. Microsoft has released a sample with documentation on how to implement a Custom Tool. The code can be found here: <br /><a href="http://code.msdn.microsoft.com/SingleFileGenerator">http://code.msdn.microsoft.com/SingleFileGenerator</a></p> <p><a href="http://go.microsoft.com/fwlink/?LinkID=186904">Visual Studio 2010 SDK</a> must be installed.</p> <p>The documentation states “Rebuild the class library and start running it”. Didn’t work. Got the error message saying a class library cannot be started. To be able to debug this is what I did:</p> <ol> <li>In <strong>Solution Explorer</strong>, right click on <strong>Generator Sample</strong> and select the menu item <strong>Properties</strong>.</li> <li>On the <strong>Debug</strong> tab, click the <strong>Start external program radio button</strong>.</li> <li>Browse or enter the path to VS 2010, typically: <br /><strong>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe</strong></li> <li>As <strong>Command line arguments</strong>, enter <br /><strong>/ranu /rootsuffix Exp</strong></li> <li>As <strong>Working directory</strong>, specify the folder for VS2010: <br /><strong>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe</strong></li> <li>Set a break point in the XmlClassGenerator.GenerateCode method.</li> <li>Press F5 to start debugging.</li> <li>A new Visual Studio is started.</li> <li>Follow the instructions in the <a href="http://code.msdn.microsoft.com/SingleFileGenerator/Release/ProjectReleases.aspx">documentation</a> (create a new class library, create an xml file, fill with content, set CustomTool for file) and the break point will be hit.</li> </ol> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-75017030043516191602009-12-03T21:45:00.001+01:002009-12-03T21:47:06.898+01:00How to remotely connect to ASP.Net Development Server<p>The ASP.Net Development Server (webdev.webserver.exe), which is included with Visual Studio, is used when testing web applications locally when IIS isn’t installed. The ASP.Net Development Server will only serve pages to browser requests on the local computer, so a colleague of yours cannot have a look at what you’re doing, since ASP.Net Development Server will not serve pages to another computer. </p> <p><a href="http://lh3.ggpht.com/_uLEBEDJEESU/Sxgje8oreSI/AAAAAAAAAGs/0C5tWoiPCpo/s1600-h/image%5B2%5D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_uLEBEDJEESU/Sxgjfdq9iRI/AAAAAAAAAGw/md7NIDp7fcs/image_thumb.png?imgmax=800" width="244" height="78" /></a> </p> <p>In order to remotely connect to the ASP.Net Development Server a proxy must be used that accepts remote connections and proxies traffic to and from the ASP.Net Development Server.</p> <p>I searched the internet for a suitable proxy but I couldn’t find one that is small and easy to use (ok, I admit, I didn’t search <em>that</em> long :-) so I wrote one based on proxy code from <a title="http://www.mentalis.org/soft/projects/proxy/" href="http://www.mentalis.org/soft/projects/proxy/">http://www.mentalis.org/soft/projects/proxy/</a>.  It’s probable not the most elegant piece of code ever written but it will have to do.</p> <p>To start the proxy just pass the port number to it:</p> <pre>Proxy.exe 62200</pre>
<p>Incoming traffic to port 80 (standard http port) is proxied to 62200, so if your computer’s name is YourComputer, your colleague can connect on the url: http://YourComputer/</p>
<p>To listen to another port than 80, specify it as the second argument:</p>
<p></p>
<pre>Proxy.exe 62200 15555</pre>
<p>Incoming traffic to port 15555  is proxied to 62200, so the url will be: http://YourComputer:15555/</p>
<h2>Download</h2>
<p>Download executable and source here:
<br /><a title="http://cid-1591ce8777facfb4.skydrive.live.com/browse.aspx/Public/Code/Proxy" href="http://cid-1591ce8777facfb4.skydrive.live.com/browse.aspx/Public/Code/Proxy">http://cid-1591ce8777facfb4.skydrive.live.com/browse.aspx/Public/Code/Proxy</a></p> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-39542629932223444802008-12-18T17:32:00.001+01:002008-12-18T17:32:31.618+01:00How to deploy a VS Database Project GDR using vsdbcmd<p>With the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=bb3ad767-5f69-4db9-b1c9-8f55759846ed&displaylang=en">release of Visual Studio Team System 2008 Database Edition GDR</a> we now have the possibility to use a standalone command for deploying a database project. Unfortunately the documentation for the new vsdbcmd is so full of errors that you cannot use it, see for example “Command-line Reference for VSDBCMD (Deployment and Schema Import)” and “How to: Prepare a Database for Deployment From a Command Prompt by Using VSDBCMD ”. Seems to be written for a previous version. </p> <h2>Properties</h2> <p>The documentation states that you should specify properties using this syntax:</p> <pre>/p:PropertyName:PropertyValue INCORRECT!</pre>
<p>The correct syntax is:</p>
<pre>/p:PropertyName=PropertyValue </pre>
<h2>Verbose and quiet</h2>
<p>It also states that there exists a /verbose or /v option. This option do not exist. It has been removed. It’s verbose by default and you can use the undocumented /quiet or /q to turn of verbosity [<a href="http://social.msdn.microsoft.com/Forums/en-US/vstsdb/thread/e188dd40-dfe0-45a0-b75b-fcf7d187c2b9/#f9ee85f4-4ea9-4646-9d6d-75162fa77535">source</a>].</p>
<h2>Invalid property names</h2>
<p>The common deployment properties list isn’t right either. For example the TargetDatabaseName is in fact called TargetDatabase. Have a look in the .sqldeployment and .deploymanifest files for proper naming. These files exists in the directory created when building the project, for example MyDbProject/sql/debug/.</p>
<h2>Deploy-example</h2>
<p>Below is an example of how to deploy a database project that has been built by Visual Studio or Team Server Foundation (TFS). </p>
<p>Start a command prompt and change directory to the directory that was created when the project was built (for example MyDbProject/sql/debug/) and execute the command below (on a single line).</p>
<pre>"%ProgramFiles%\Microsoft Visual Studio 9.0\VSTSDB\deploy\vsdbcmd"<br /> /a:Deploy <br /> /ConnectionString:"Data Source=<em>MyServer</em>;Integrated Security=True;" <br /> /dsp:SQL <br /> /manifest:<em>MyDbProject</em>.deploymanifest <br /> /p:TargetDatabase=<em>MyDb</em> <br /> /dd</pre>
<p>This will create a .sql file and deploy it, i.e. execute it on the server. If you remove the /dd option the .sql will be created but not deployed.</p> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com2tag:blogger.com,1999:blog-4681772286990545567.post-43370664076209833632008-07-27T13:59:00.001+02:002008-07-27T13:59:19.912+02:00How to include scripts after asp.net ajax framework's<div class="otherLanguage"><a href="http://hockeswe.blogspot.com/2008/07/inkludera-script-efter-aspnet-ajax.html">Swedish version of this entry</a> </div> <p>When registering script includes using <a href="http://msdn.microsoft.com/sv-se/library/system.web.ui.scriptmanager.registerclientscriptinclude(en-us).aspx">ScriptManager.RegisterClientScriptInclude("myFile.js")</a> the files are always included before the frameworks. This causes errors if your code depends on the ajax framework's. Errors like "Type is not defined" are common since the first line in the included script file often tries to register a namespace: Type.registerNamespace('My.Namespace');</p> <p>On the other hand, files registered as ScriptReferences on the ScriptManagerProxy will be included AFTER the framework's includes.</p> <pre class="csharpcode"><span class="kwrd"><</span><span class="html">asp:ScriptManagerProxy</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="attr">id</span><span class="kwrd">="ScriptManagerProxy1"</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">Scripts</span><span class="kwrd">><</span><span class="html">asp:ScriptReference</span> <span class="attr">Path</span><span class="kwrd">="~/anotherFile.js"</span> <span class="kwrd">/></</span><span class="html">Scripts</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">asp:ScriptManagerProxy</span><span class="kwrd">></span></pre>
<p>Not exactly the expected behavior and certainly not what we want.</p>
<p>When calling <a href="http://msdn.microsoft.com/sv-se/library/system.web.ui.scriptmanager.registerclientscriptinclude(en-us).aspx">ScriptManager</a>.RegisterClientScriptInclude() it delegates to the class ClientScriptManager. This class holds, internally, a list of registered scripts, and new entries ends up at the end. So the call ScriptManager.RegisterClientScriptInclude("myFile.js") will put myFile.js at the end of that list. Like this:</p>
<pre>ClientScriptManagerClientScripts = { ..., "~/myFile.js" }</pre>
<p>The references in the ScriptManagerProxies are handled a bit differently. The ScriptManager will, on the event PagePreRenderComplete, collect all references from the proxies in a list, and first in that list put the ajax framework's files. </p>
<pre>List in ScriptManager = { ajax framework files, "~/anotherFile.js" }</pre>
<p>After being collected the files are registered with the ClientScriptManager and are appended at the end of it's list. Since we registered myFile.js before PagePreRenderComplete (which occurs late in the asp.net page's life cycle), myFile.js is before the framework's files:</p>
<p></p>
<pre>ClientScriptManagerClientScripts = { ..., "~/myFile.js", ..., ajax framework files, "~/anotherFile.js"}</pre>
<p>These are rendered to the page in this order and it explains why anotherFile.js may use the framework directly and myFile.js not.</p>
<h2>Solution 1. Use a proxy</h2>
<p>The simplest solution is to put a ScriptManagerProxy on the page (or user control, or MasterPage) and either, as shown above declare a ScriptReference, or add one by code:</p>
<pre class="csharpcode">ScriptManagerProxy1.Scripts.Add(<span class="kwrd">new</span> ScriptReference(<span class="str">"~/myFile.js"</span>));</pre>
<h2>Solution 2. Register the file after PagePreRenderComplete</h2>
<p>If you somehow manage to register myFile.js after PagePreRenderComplete (i.e. after ScriptControl has added all files) it will end up after the framework's files. But you'll need to do it before the rendering takes place. Between PreRender and Render phases is the SaveViewState phase. If we override SaveViewState on a control (Page is also a control) and registers myFile.js there it will be added to the list after the framework's files. This is sort of a hack and it's not guaranteed to work when new versions of the framework are released, but: It works.</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">object</span> SaveViewState()
{
ScriptManager.RegisterClientScriptInclude(<span class="kwrd">this</span>,GetType(),<span class="str">"myFile"</span>,<span class="str">"~/myFile.js"</span>);
<span class="kwrd">return</span> <span class="kwrd">base</span>.SaveViewState();
}</pre>
<h2>Solution 3. Your own ScriptManager</h2>
<p>This is, at least to me, the most elegant solution. Basically: you create the class MyScriptManager, which derives from ScriptManager; you replace the ScriptManager on the page (or user control, or MasterPage) with MyScriptManager; add the method RegisterClientScriptInclude(string url) to MyScriptManager and by some magic inside MyScriptManager makes sure that files registered thru the new method will be rendered after the ajax framework's includes.</p>
<p>When the ScriptManager collects all the ScriptReferences from the proxies (as explained above) it also collects ScriptReferences from all controls that have been registered with the ScriptManager as ScriptControls, by calling the method GetScriptReferences, that ScriptControls must implement. These files will be added after the proxies' files.</p>
<p>This is what we'll do: The new RegisterClientScriptInclude method will only add the url to a list, and not register it anywhere else. We let MyScriptManager be a ScriptControl (i.e. implement IScriptControl) and register itself as such. In the method GetScriptReferences we will, when requested, supply the list of registered files, and they will end up after the framework's.</p>
<p>Not much code is needed.</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> MyScriptManager : ScriptManager, IScriptControl
{
<span class="kwrd">private</span> List<<span class="kwrd">string</span>> _registeredScripts = <span class="kwrd">new</span> List<<span class="kwrd">string</span>>();
<span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> RegisterClientScriptInclude(<span class="kwrd">string</span> url)
{
_registeredScripts.Add(url);
}
<span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnPreRender(EventArgs e)
{
<span class="rem">//Register this instance as a ScriptControl.</span>
RegisterScriptControl(<span class="kwrd">this</span>);
<span class="kwrd">base</span>.OnPreRender(e);
}
<span class="kwrd">public</span> <span class="kwrd">new</span> <span class="kwrd">static</span> MyScriptManager GetCurrent(Page page)
{
<span class="kwrd">return</span> (MyScriptManager) ScriptManager.GetCurrent(page);
}
<span class="preproc">#region</span> IScriptControl Members
IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
{
<span class="kwrd">return</span> <span class="kwrd">null</span>;
}
IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
<span class="rem">//For each element in _registeredScripts create a
//ScriptReference and return the IEnumerable</span>
<span class="kwrd">return</span> _registeredScripts.ConvertAll(s => <span class="kwrd">new</span> ScriptReference(s));
}
<span class="preproc">#endregion</span>
}</pre>
<p>Please note that I've simplified the code in order to show the concept. In production code you'll want to encapsulate the list in a public property that creates the list if needed. And you want two protected virtual versions of GetScriptDescriptors and GetScriptReferences that the existing ones will call. </p>
<p>To register a file to be included after the framework's files you use:</p>
<pre class="csharpcode">MyScriptManager.GetCurrent(Page).RegisterClientScriptInclude(<span class="str">"~/myFile.js"</span>);</pre>
<p>If you're using AjaxControlToolkit change the inheritance to ToolkitScriptManager.</p>
<p>Note the order the files are included: </p>
<ol>
<li>ScriptManager.RegisterClientScriptInclude registered files </li>
<li>Ajax framework's files </li>
<li>All ScriptManagerProxy ScriptReferences </li>
<li>MyScriptManager.RegisterClientScriptInclude registered files </li>
</ol>
<p>If you want your files to be included between 2 and three you're in deep water. It's probably doable but far from trivial, since ScriptManager is pretty closed for extension. It would be nice if Microsoft adhered the <a href="http://en.wikipedia.org/wiki/Open/closed_principle">Open/Closed-principle</a> a bit more. :)</p> Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com2tag:blogger.com,1999:blog-4681772286990545567.post-14656184021784434442007-07-27T17:33:00.001+02:002007-07-27T17:35:05.936+02:00AutoEventWireup=true<div class="otherLanguage"><a href="http://hockeswe.blogspot.com/2007/07/autoeventwireuptrue.html">Swedish version of this entry</a></div> <p>If you specify the attribute <em>AutoEventWireup=True</em> on a Web User Control or a Page, methods like <em>Page_Init() </em>och <em>Page_Load() </em>will be automatically routed to the page's <em>Init</em>- and <em>Load</em>-events.</p> <p>This is good, sometimes. It simplifies for you since you don't have to hook up events to event handlers. But it is something that's done during runtime, and therefore adds to the executiion time and it may cause event handlers to be called many times.</p> <p><strong>Example: Event handler beeing called twice.</strong></p><pre class="code"><span style="color: rgb(0,0,255)">protected</span> <span style="color: rgb(0,0,255)">void</span> Page_Init()
{
Page.Load += Page_Load;
}
<span style="color: rgb(0,0,255)">protected</span> <span style="color: rgb(0,0,255)">void</span> Page_Load(<span style="color: rgb(0,0,255)">object</span> sender, <span style="color: rgb(43,145,175)">EventArgs</span> e)
{
<span style="color: rgb(0,128,0)">//This code will execute twice
</span>}</pre><a href="http://11011.net/software/vspaste"></a>
<p><em>Page_Load</em> in the example above will be called twice. Once since you mannually hooked the event to the <em>Page_Load</em> handler. Another time since <em>AutoEventWireup=true</em> and the method has a name causing the event to automatically be hooked to it.</p>
<p><em>AutoEventWireup</em> works on <em>TemplateControl</em> which both <em>Page</em> och <em>Web User Controls</em> derives from. </p>
<p><a href="http://odetocode.com/Blogs/scott/archive/2006/02/16/2914.aspx">K Scott Allen's blog</a> talkes about this. I'll go more into depths.</p>
<h2>SupportAutoEvents</h2>
<p>What happens when <em>AutoEventWireup=true?</em> A <em>TemplateControl</em> has a property <em>SupportAutoEvents</em>. This is t<em>rue</em> by default (and will change to <em>false</em> by the parser/control builderif you set the attribute <em>AutoEventWireup=false</em>).</p>
<h2>HookUpAutomaticHandlers </h2>
<p><em>TemplateControl.HookUpAutomaticHandlers</em> (which is called during the <em>OnInit</em>) will, if <em>AutoEventWireup=true</em> try to find methods with these names:</p>
<ul>
<li>If the control is a <em>Page</em>:
<ul>
<li>Page_PreInit
<li>Page_PreLoad
<li>Page_LoadComplete
<li>Page_PreRenderComplete
<li>Page_InitComplete
<li>Page_SaveStateComplete </li></ul>
<li>For all <em>TemplateControls</em>:
<ul>
<li>Page_Init
<li>Page_Load
<li>Page_DataBind
<li>Page_PreRender
<li>Page_Unload
<li>Page_Error
<li>Page_AbortTransaction or if it does not exist; OnTransactionAbort
<li>Page_CommitTransaction or if it does not exist; OnTransactionCommit</li></ul></li></ul>
<p>This is carried out in <em>TemplateControl.GetDelegateInformationWithNoAssert()</em>.</p>
<h3>32 attempts</h3>
<p>As <a href="http://odetocode.com/Blogs/scott/archive/2006/02/16/2914.aspx">K Scott Allen</a> writes two attempts will be made for every name. First it will try to find an <em>EventHandler</em> with the specified name, i.e. a method with the signature:</p><pre class="code"><span style="color: rgb(0,0,255)">void</span> EventHandler(<span style="color: rgb(0,0,255)">object</span> sender, <span style="color: rgb(43,145,175)">EventArgs</span> e)</pre><a href="http://11011.net/software/vspaste"></a>
<p><strong>Exemple: A method that is an EventHandler</strong></p><pre class="code"><span style="color: rgb(0,0,255)">void</span> Page_PreInit(<span style="color: rgb(0,0,255)">object</span> sender, <span style="color: rgb(43,145,175)">EventArgs</span> e)</pre><a href="http://11011.net/software/vspaste"></a>
<p>If that fails a VoidMethod is searched for, i.e. a method with the signature:</p><pre class="code"><span style="color: rgb(0,0,255)">void</span> VoidMethod()</pre>
<p><strong><strong>Exemple: A method that is a</strong> VoidMethod</strong></p><pre class="code"><span style="color: rgb(0,0,255)">void</span> Page_PreInit()</pre>
<p>Although no methods matching the list have been added to the Page, 32 attempts to find a method will be made (K Scott Allen got 28 but he must have forgotten about OnTransactionAbort and OnTransactionCount).</p>
<p>Ok, the result will be cached but the search will be made at least once, at that's for every TemplateControl. </p>
<h3>Hook up the event to the handler</h3>
<p>For all matching methods on the control <em>TemplateControl.HookUpAutomaticHandlers()</em> will hook up the event to the corresponding event handler, unless the method already has been added to the event since <em>HookUpAutomaticHandlers</em> searches the list of event handlers for the event. If it finds the method, it will not add the method again.</p>
<p>But wait. In the first example <em>Page_Load()</em> was obviously added twice to the event. <br>Yes, but that's because <em>HookUpAutomaticHandlers</em> already had hooked up the <em>Page.Load</em> event to the <em>Page_Load</em> handler when we in <em>Page_Init </em>did it. Remember that <em>HookUpAutomaticHandlers</em> is called in the Page's <em>OnInit</em>, which is called before our <em>Page_Init</em> method. If we hook up the event to the handler <strong>before</strong> the page's <em>OnInit</em> we will do it before the <em>HookUpAutomaticHandlers</em> has ben called and therefore <em>Page_Load</em> will only be called once.</p>
<p><strong>Exemple: Page_Load is only called once.</strong></p><pre class="code"><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">partial</span> <span style="color: rgb(0,0,255)">class</span> <span style="color: rgb(43,145,175)">_Default</span> : System.Web.UI.<span style="color: rgb(43,145,175)">Page
</span>{
<span style="color: rgb(0,0,255)">public</span> _Default()
{
Page.Load += Page_Load;
}
<span style="color: rgb(0,0,255)">protected</span> <span style="color: rgb(0,0,255)">void</span> Page_Load(<span style="color: rgb(0,0,255)">object</span> sender, <span style="color: rgb(43,145,175)">EventArgs</span> e)
{
<span style="color: rgb(0,128,0)">//This code will execute once
</span> }
}</pre>
<h2>Conclusion: AutoEventWireup=false</h2>
<p>Consider setting <em>AutoEventWireup=false</em> and manually hook up the events to the handlers. You gain control over when things are called and you don't have to pay for the overhead <em>TemplateControl.HookUpAutomaticHandlers</em> causes. </p>
<p>Microsoft recommends setting it to <em>false</em> if performance is a key consideration.</p>
<h2>More on AutoEventWireup on MSDN</h2>
<p><a title="http://msdn2.microsoft.com/en-us/library/system.web.configuration.pagessection.autoeventwireup.aspx" href="http://msdn2.microsoft.com/en-us/library/system.web.configuration.pagessection.autoeventwireup.aspx">http://msdn2.microsoft.com/en-us/library/system.web.configuration.pagessection.autoeventwireup.aspx</a><br><a title="http://support.microsoft.com/default.aspx/kb/324151" href="http://support.microsoft.com/default.aspx/kb/324151">http://support.microsoft.com/default.aspx/kb/324151</a></p>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-75486929396693031472007-05-21T15:09:00.000+02:002007-05-21T15:42:32.051+02:00Insert Do-nothing comments<div class="otherLanguage"><a href="http://hockeswe.blogspot.com/2007/05/infoga-do-nothing-kommentarer.html">Swedish version of this entry</a></div>Always insert a <code>//Do nothing</code> comment in places where the intention is that nothing should be done.
Let Me show you why by an example. Assume you have a constructor for a Control that inherits WebControl and all you want to do is changing the default tag (which is Span).<pre class="csharpcode"><span class="kwrd">public</span> MyControl()
:<span class="kwrd">base</span>(HtmlTextWriterTag.Div)
{
}</pre>When someone else reads this code (or you in a month or so when you've forgotten all about it) they might wonder if this code has been finished or if there is something missing in the constructor. By adding a comment, you show for anyone reading the code that there shouldn't really be any code inside the constructor.<pre class="csharpcode"><span class="kwrd">public</span> MyControl()
:<span class="kwrd">base</span>(HtmlTextWriterTag.Div)
{
<span class="highlight rem">//Do nothing</span>
}</pre>
I have a code snippet for this so I just need to type <code>don</code> and hit tab twice and <code>//Do nothing</code> is inserted.Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-86169543973534577722007-05-18T10:23:00.000+02:002007-05-20T00:57:06.034+02:00Passing values to behavior properties<div class="otherLanguage"><a href="http://hockeswe.blogspot.com/2007/05/english-version-of-this-entry-en.html">Swedish version of this entry</a></div>Typically a property in a AjaxControlToolkit Extender looks like this:
<pre>[ExtenderControlProperty]
[DefaultValue("")]
public string MyProperty
{
get { ... }
set { ... }
}</pre>Which will match a property in the behavior:<pre>get_MyProperty : function() { ... },
set_MyProperty : function(value) { ... }</pre>
Values for <code>MyProperty</code> on the server side will end up in the behavior.
Sometimes you want to pass values to the behavior without creating a property in the Extender control. To do this, simply override <code>RenderScriptAttributes()</code> and add the properties using <code>AddProperty()</code>.<pre>protected override void RenderScriptAttributes(ScriptBehaviorDescriptor descriptor)
{
base.RenderScriptAttributes(descriptor);
string horizontalAlignment=GetHorizontalAlignment();
descriptor.AddProperty("HorizontalAlignment", horizontalAlignment);
}</pre>
And voilà, the <b>HorizontalAlignment</b> property in the beahvior will be set.Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-84315965297753259692007-05-18T09:39:00.000+02:002007-05-20T00:46:55.804+02:00Property names & Extenders<div class="otherLanguage"><a href="http://hockeswe.blogspot.com/2007/05/namn-p-properties-i-ajax-extenders.html">Swedish version of this entry</a></div>Properties for extenders inheriting <code>ExtenderControlBase</code> typically looks like this:
<pre>[ExtenderControlProperty]
[DefaultValue("")]
public string MyProperty
{
get
{
return GetPropertyValue("MyProperty", "");
}
set
{
SetPropertyValue("MyProperty", value);
}
}</pre>
You must have a property with the same name in the behavior on the client side:
<pre>get_MyProperty : function() {
return this._myProperty;
},
set_MyProperty : function(value) {
this._myProperty = value;
}</pre>
But what if you want it to have different name on the client side? Easy. Add the <code>ClientPropertyName</code> attribute to the server side property. If we want <code>MyProperty</code> to be called <b>myProp</b> instead this is how it's done:
<pre>[ExtenderControlProperty]
[DefaultValue("")]
<span class="highlight">[ClientPropertyName("myProp")]</span>
public string MyProperty
{
get
{
return GetPropertyValue("MyProperty", "");
}
set
{
SetPropertyValue("MyProperty", value);
}
}</pre>
On the client side we get:
<pre>get_<span class="highlight">myProp</span> : function() {
return this._myProperty;
},
set_<span class="highlight">myProp</span> : function(value) {
this._myProperty = value;
}</pre>
More on attributes:
<a href="http://ajax.asp.net/ajaxtoolkit/Walkthrough/ExtenderClasses.aspx">http://ajax.asp.net/ajaxtoolkit/Walkthrough/ExtenderClasses.aspx</a>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-29728669762732650242007-05-10T12:28:00.000+02:002007-05-20T00:30:10.914+02:00OOP in Javascript<div class="otherLanguage"><a href="http://hockeswe.blogspot.com/2007/05/english-version-of-this-entry-msdn.html">Swedish version of this entry</a></div>MSDN Magazine May 2007 edition has an interesting article on how to use object oriented techniques in Javascript. A must-read if you are using Microsoft AJAX since the entire client script library is written using these techniques.
<a href="http://msdn.microsoft.com/msdnmag/issues/07/05/JavaScript/default.aspx">http://msdn.microsoft.com/msdnmag/issues/07/05/JavaScript/default.aspx</a>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-82676618898027490742007-03-22T16:16:00.000+01:002007-05-20T00:23:53.688+02:00Validators not working with UpdatePanel??<div class="otherLanguage"><a href="http://hockeswe.blogspot.com/2007/05/validators-fungerar-inte-med.html">Swedish version of this entry</a></div>The validators don't work very well sometimes when put in an UpdatePanel. But they used to...
The reason is that in the 1.0 release of Ajax asp.net the validators that were used in place of the the ordinary asp.net validators have been removed. There was supposed to be an update available for the System.Web namespace to overcome this problem but it will take some time before we have the update. In the meantime there is a fix available.
Have a look here: <a href="http://blogs.msdn.com/mattgi/archive/2007/01/23/asp-net-ajax-validators.aspx">http://blogs.msdn.com/mattgi/archive/2007/01/23/asp-net-ajax-validators.aspx</a>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-57714575369342273162007-02-16T10:49:00.000+01:002007-03-22T13:41:05.586+01:00Shortcuts and Cheat SheetsKeyboard shortcuts for VS 20005:
<a href="http://blogs.msdn.com/robcaron/archive/2007/01/29/1552795.aspx">http://blogs.msdn.com/robcaron/archive/2007/01/29/1552795.aspx</a>
Regular Expressions cheat sheet:
<a href="http://www.ilovejackdaniels.com/cheat-sheets/regular-expressions-cheat-sheet/">http://www.ilovejackdaniels.com/cheat-sheets/regular-expressions-cheat-sheet/</a>
CSS cheat sheet
<a href="http://www.ilovejackdaniels.com/cheat-sheets/css-cheat-sheet/">http://www.ilovejackdaniels.com/cheat-sheets/css-cheat-sheet/</a>
JavaScript cheat sheet
<a href="http://www.ilovejackdaniels.com/cheat-sheets/javascript-cheat-sheet/">http://www.ilovejackdaniels.com/cheat-sheets/javascript-cheat-sheet/</a>
Asp.net Lifecycle:
<a href="http://john-sheehan.com/blog/index.php/net-cheat-sheets/">http://john-sheehan.com/blog/index.php/net-cheat-sheets/</a>
AJAX asp.net
<a href="http://aspnetresources.com/blog/ms_ajax_cheat_sheets_batch2.aspx">http://aspnetresources.com/blog/ms_ajax_cheat_sheets_batch2.aspx</a>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-40840312333725457092007-02-08T14:45:00.000+01:002007-05-20T00:15:42.788+02:00Don't access the property ClientId to early<div class="otherLanguage"><a href="http://hockeswe.blogspot.com/2007/02/fippla-inte-med-clientid-fr-tidigt.html">Swedish version of this entry</a></div>The ClientId property on a Control is correct only after the control has been added to a Parent, i.e. added to a Controls collection. The parent must also be connected to a parent, and it's parent, and so on up al the way to the Page control.
If you try to get ClientId to early, not only will you get something unusable, it will be cached so all subsequent calls will get the same. It will also prevent postback events from working.
Big No-no:
<pre>public class MyControl : CompositeControl
{
protected override void CreateChildControls()
{
Button myButton = new Button();
myButton.Text = "Unclicked";
myButton.Click += new EventHandler(myButton_Click);
Controls.Add(myButton);
//MyControl has no parent yet. The following code will prevent
//the myButton_Click from beeing called when the button is clicked.
//Remove the line and it will be called.
<span class="highlight">string id = myButton.ClientID; </span>
}
void myButton_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
button.Text = "clicked";
}
}
</pre>
Another example: <a href="http://aspadvice.com/blogs/joteke/archive/2007/01/28/Accessing-ClientID-or-UniqueID-too-early-can-cause-issues.aspx">http://aspadvice.com/blogs/joteke/archive/2007/01/28/Accessing-ClientID-or-UniqueID-too-early-can-cause-issues.aspx</a>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com0tag:blogger.com,1999:blog-4681772286990545567.post-87509435780243840992007-01-31T18:08:00.000+01:002007-05-19T23:59:10.905+02:00Find a control in javascript (Ajax ASP.Net)<div class="otherLanguage"><a href="http://hockeswe.blogspot.com/2007/01/hitta-en-kontroll-i-javascript-ajax.html">Swedish version of this entry</a></div>To find a control with id "MyControl" us the function $get.
Example:<pre>alert(<span class="highlight">$get("MyControl")</span>.id);</pre>Håkan Canbergerhttp://www.blogger.com/profile/07785350579880064843noreply@blogger.com2