<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-50548299979181668</id><updated>2024-10-07T06:40:12.508+01:00</updated><category term="TEAM.Commons"/><category term="Patterns"/><category term="My Applications"/><category term="ASP.NET MVC"/><category term="C#"/><category term="MVC"/><category term="Single Action Controllers"/><category term="CQRS"/><category term="JavaScript"/><category term="Parallelization"/><category term="Queries"/><category term="Threading"/><category term="Unobtrusive"/><category term="aspnetcore"/><title type='text'>Rodolfo Grave</title><subtitle type='html'>Let&#39;s get technical</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default?alt=atom&amp;redirect=false'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default?alt=atom&amp;start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>49</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-601562520480544450</id><published>2017-09-30T22:41:00.000+01:00</published><updated>2017-09-30T22:42:25.378+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="aspnetcore"/><category scheme="http://www.blogger.com/atom/ns#" term="Patterns"/><title type='text'>How to integration test ASP.NET Core services, including Startup and dependency injection</title><content type='html'>After 3 years, I feel I have something valuable to share.&lt;br /&gt;
&lt;br /&gt;
I have recently started to work with ASP.NET Core and even though it&#39;s a thousand times easier to test than ASP.NET MVC, thanks to its built-in Dependency Injection (IServiceCollection, IServiceProvider) and the very great TestServer, I could not find a well rounded pattern to easily test all aspects of an application, mocking at different levels and using the powerful fact that everything comes from the IServiceProvider by design.&lt;br /&gt;
&lt;br /&gt;
This is very much work in progress so please, if you happen to come across this page, get in touch with any alternatives you have found or any improvements you think can be applied.&lt;br /&gt;
&lt;br /&gt;
Maintaining my style, let&#39;s get on with some code. It&#39;s worth more than a thousand words.&lt;br /&gt;
&lt;br /&gt;
This is what I consider the ideal integration/acceptance/end-to-end test:&lt;br /&gt;
&lt;br /&gt;
&lt;table class=&quot;highlight tab-size js-file-line-container&quot; data-tab-size=&quot;8&quot; style=&quot;background-color: white; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; color: #24292e; font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;; font-size: 14px; tab-size: 8;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC1&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;&lt;span class=&quot;pl-k&quot; style=&quot;box-sizing: border-box; color: #d73a49;&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;pl-k&quot; style=&quot;box-sizing: border-box; color: #d73a49;&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1;&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1;&quot;&gt;WhenXThenY&lt;/span&gt;(&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;2&quot; id=&quot;file-aspnetcoretest-cs-L2&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC2&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;&lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1;&quot;&gt;IRepository&lt;/span&gt;&amp;lt;&lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1;&quot;&gt;SomeEntity&lt;/span&gt;&amp;gt; &lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box;&quot;&gt;repository&lt;/span&gt;, &lt;span class=&quot;pl-c&quot; style=&quot;box-sizing: border-box; color: #6a737d;&quot;&gt;// For this to work, a TestServer must have been started and&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;3&quot; id=&quot;file-aspnetcoretest-cs-L3&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC3&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;&lt;span class=&quot;pl-c&quot; style=&quot;box-sizing: border-box; color: #6a737d;&quot;&gt;// this IRepository must be the same instance that the Controller is going to use when processing the request&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;4&quot; id=&quot;file-aspnetcoretest-cs-L4&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC4&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;&lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1;&quot;&gt;WebApiClient&lt;/span&gt; &lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box;&quot;&gt;client&lt;/span&gt;, &lt;span class=&quot;pl-c&quot; style=&quot;box-sizing: border-box; color: #6a737d;&quot;&gt;// This must be wrapping an HttpClient connected to the TestServer &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;5&quot; id=&quot;file-aspnetcoretest-cs-L5&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC5&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;&lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1;&quot;&gt;ISomeExternalServiceGateway&lt;/span&gt; &lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box;&quot;&gt;gateway&lt;/span&gt; // Must also be the same instance to be used by the Controller)&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;6&quot; id=&quot;file-aspnetcoretest-cs-L6&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC6&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;{&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;7&quot; id=&quot;file-aspnetcoretest-cs-L7&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC7&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;&lt;span class=&quot;pl-k&quot; style=&quot;box-sizing: border-box; color: #d73a49;&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1;&quot;&gt;entityInRequiredState &lt;/span&gt;= CreateEntityInStateX();&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;8&quot; id=&quot;file-aspnetcoretest-cs-L8&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC8&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;repository.GetById(entityInRequiredState.Id).Return(entityInRequiredState);&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;9&quot; id=&quot;file-aspnetcoretest-cs-L9&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC9&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;&lt;span class=&quot;pl-k&quot; style=&quot;box-sizing: border-box; color: #d73a49;&quot;&gt;await&lt;/span&gt; client.Post(&lt;span class=&quot;pl-pds&quot; style=&quot;box-sizing: border-box; color: #032f62;&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;pl-s&quot; style=&quot;box-sizing: border-box; color: #032f62;&quot;&gt;controller/action/&lt;/span&gt;{entityInRequiredState.Id}&lt;span class=&quot;pl-pds&quot; style=&quot;box-sizing: border-box; color: #032f62;&quot;&gt;&quot;&lt;/span&gt;);&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;10&quot; id=&quot;file-aspnetcoretest-cs-L10&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC10&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;entityInRequiredState.ShouldBeInStateY();&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-num js-line-number&quot; data-line-number=&quot;11&quot; id=&quot;file-aspnetcoretest-cs-L11&quot; style=&quot;box-sizing: border-box; color: rgba(27, 31, 35, 0.3); cursor: pointer; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; min-width: 50px; padding: 0px 10px; text-align: right; user-select: none; vertical-align: top; white-space: nowrap; width: 50.303px;&quot;&gt;&lt;/td&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line&quot; id=&quot;file-aspnetcoretest-cs-LC11&quot; style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;}

&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;16e603a86565536063932e03fa4afc10&quot; id=&quot;gist-16e603a86565536063932e03fa4afc10&quot;&gt;
&lt;a href=&quot;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-aspnetcoretest-cs&quot;&gt;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-aspnetcoretest-cs&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
There are a few things to notice here:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Somehow, a &lt;a href=&quot;https://docs.microsoft.com/en-us/aspnet/core/testing/integration-testing&quot;&gt;TestServer&lt;/a&gt; must be started using as much of the production configuration as possible. Obviously, we still need to be able to mock what we want.&lt;/li&gt;
&lt;li&gt;The WebApliClient must send its requests to the &lt;a href=&quot;https://docs.microsoft.com/en-us/aspnet/core/testing/integration-testing&quot;&gt;TestServer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The IRepository&lt;someentity&gt; must be the same that is going to be used by the Controller when processing the request, otherwise our setup is useless.&lt;/someentity&gt;&lt;/li&gt;
&lt;li&gt;We need to use a framework that lets you decorate your tests to customize the way the parameters are injected. I&#39;m currently using &lt;a href=&quot;https://github.com/AutoFixture&quot;&gt;AutoFixture&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
The key to make this work is to use the IServiceProvider used by the server as the source for all the instances you want to configure to setup your test. Turns out this is not trivial to achieve without doing some research and understanding some ASP.NET Core secrets, which is why I think this is a valuable thing to share.&lt;br /&gt;
&lt;br /&gt;
The typical code to start an ASP.NET Core web server is:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-defaultaspnetcoreprogram-cs&quot;&gt;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-defaultaspnetcoreprogram-cs&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The trick to get access to the IServiceProvider created by the WebHostBuilder, and the reason I&#39;m sharing all this, is to provide an instance of IStartup instead of the type:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-modifiedaspnetcoreprogram-cs-L13&quot;&gt;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-modifiedaspnetcoreprogram-cs-L13&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
With the above in place, we can now use AutoFixture to create an instance of TestServer, keep a reference to the IServiceProvider and use it to obtain instances to be injected into the test:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;a href=&quot;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-integrationtestautodataattribute-cs&quot;&gt;attribute&lt;/a&gt;, to instruct AutoFixture how to resolve all parameters of the test method.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-webcustomization-cs&quot;&gt;AutoFixture ICustomization&lt;/a&gt; that creates a &lt;a href=&quot;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-webserverfixture-cs&quot;&gt;fixture for the TestServer&lt;/a&gt; and configures a &lt;a href=&quot;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10#file-dependenciesspecimenbuilder-cs&quot;&gt;SpecimenBuilder&lt;/a&gt; to delegate all requests to the IServiceProvider.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Apologies for not embedding the code here but Blogger refuses to accept any of the solutions I have found to embed code. I do dislike Blogger a lot but I haven&#39;t had the time and energy required to find something else.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I will probably turn all the above into a little NuGet package. In the meantime, the gist contains all you need to get it working:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10&quot;&gt;https://gist.github.com/rodolfograve/16e603a86565536063932e03fa4afc10&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;script src=&quot;https://raw.github.com/moski/gist-Blogger/master/public/gistLoader.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/601562520480544450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/601562520480544450' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/601562520480544450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/601562520480544450'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2017/09/how-to-integration-test-aspnet-core.html' title='How to integration test ASP.NET Core services, including Startup and dependency injection'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-5389328910097752769</id><published>2014-05-09T00:24:00.002+01:00</published><updated>2014-09-10T09:44:54.619+01:00</updated><title type='text'>Risk, acceptance tests, why unit tests are not enough, and what can you do about it</title><content type='html'>It&#39;s time to release again (hopefully after only 1-2 weeks after your previous release) and you must answer the question: how confident are you that the software is going to do what it&#39;s supposed to do?&lt;br /&gt;
&lt;br /&gt;
It&#39;s ultimately the &lt;a href=&quot;http://en.wikipedia.org/wiki/Scrum_(software_development)#Product_Owner&quot;&gt;Product Owner&lt;/a&gt;&#39;s decision if you should release or not, but in order to make the decision she must answer that very same question. Based on what? What information can we give her to help her support her decision?&lt;br /&gt;
&lt;br /&gt;
Most teams go about it like this:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
Hey, all &lt;b&gt;unit tests and integration tests&lt;/b&gt; are passing and we have a 98% test coverage! We&#39;ve manually checked that the software satisfies the acceptance criteria for the new stories we played, and we also did some &lt;b&gt;manual regression testing&lt;/b&gt;. Everything seems to be OK. We&#39;re happy to release.&lt;/blockquote&gt;
For a team to state they&#39;re happy to release when this is all the information they can provide is an act of faith in their skills. They&#39;re assuming that because unit tests are passing then the software is going to work as expected.&lt;br /&gt;
&lt;br /&gt;
Unfortunately we&#39;ve all been trained to fully believe in our unit tests and how good we are: surely if we test the individual methods and then the interactions by faking dependencies, we can &lt;b&gt;imply&lt;/b&gt; that everything works, right?&lt;br /&gt;
&lt;br /&gt;
Well, I&#39;d argue there are a lot of &lt;b&gt;assumptions&lt;/b&gt; and untested &lt;b&gt;implications&lt;/b&gt; in the proposition &quot;the system works because we have good &lt;b&gt;unit tests&lt;/b&gt; coverage and those tests are passing&quot;. See my &lt;a href=&quot;http://rodolfograve.blogspot.co.uk/2014/03/are-unit-tests-waste.html&quot;&gt;previous post&lt;/a&gt; about the value of unit tests, and by all means, do your Googling... the subject&#39;s been heating up recently.&lt;br /&gt;
&lt;br /&gt;
Long story short, you may have all the unit tests in the world, 100% code coverage (whatever that means), and still have no certainty that the software is going to work&amp;nbsp;&lt;b&gt;as the developers intented&lt;/b&gt;. More importantly, because unit tests verify that software does what the developers wanted, you&#39;ll have even less certainty that the software is going to do what the&amp;nbsp;&lt;b&gt;Product Owner wanted&lt;/b&gt;!&lt;br /&gt;
&lt;br /&gt;
Here&#39;s a good exercise you can do to get an idea of the implications you do in this process: take a couple of user stories you have already delivered and released, and try to make a map of the unit tests that guarantee that user story works as expected.&lt;br /&gt;
&lt;br /&gt;
Take 1 minute and think about how would you go about it right now...&lt;br /&gt;
&lt;br /&gt;
The first sign of alert should be that you had never thought about this, which is usually the case.&lt;br /&gt;
&lt;br /&gt;
In most cases only imagining the exercise should be enough, but if you go ahead and are actually able to do it then you should end up with either the realization that you have blind spots (particularly around interactions) or in the best case, a big mess of tests scathered all around the code with no clear relation to a particular acceptance test.&lt;br /&gt;
&lt;br /&gt;
If your Product Owner is not very technical then deciding to release after been given the former assessment on the quality of the release is an act of faith in the team. One most of us has been part of. If the Product Owner happens to be a techy then she&#39;s probably into the unit tests &quot;religion&quot; and is as convinced as everyone else that you can release with very high (and false) certainty things are to work as expected.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
OK, you got me thinking. What can I do?&lt;/h2&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
What if you could provide the following assessment on the quality:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
Hey, all&amp;nbsp;&lt;b&gt;unit tests&lt;/b&gt;&amp;nbsp;are passing, all the&amp;nbsp;&lt;b&gt;end-to-end automated acceptance tests&lt;/b&gt;&amp;nbsp;which run in a&amp;nbsp;&lt;b&gt;production-like environment&lt;/b&gt;&amp;nbsp;are passing. We&#39;ve done some&amp;nbsp;&lt;b&gt;manual exploratory testing&lt;/b&gt;&amp;nbsp;and didn&#39;t find any issues.&lt;/blockquote&gt;
&lt;blockquote&gt;
The automated acceptance tests cover 83% of all the acceptance tests, 98% of those considered critical and 95% of the new acceptance tests we&#39;ve just implemented.&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
We&#39;re happy to release.&lt;/blockquote&gt;
If you&#39;ve followed your process correctly then acceptance tests represent all your Product Owner cares about. If you can tell the Product Owner 83% of the acceptance tests have been verified in a production-like environment you&#39;re basically telling her that at least 83% of the features are known to work (the only risk being how different from production the test environment is). And she can now make an informed decision of the type &quot;no, I really need X and Y to be verified&quot; or &quot;great, let&#39;s go ahead&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
But isn&#39;t the end-to-end automation of acceptance tests expensive?&lt;/h2&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Yes, it is. It will consume time you could spend doing something else, like implementing new features. But assuming your software is of a reasonable complexity it should very quickly be impossible to manually verify each acceptance test which is why I included &lt;b&gt;risk&lt;/b&gt;&amp;nbsp;in the title.&lt;br /&gt;
&lt;br /&gt;
It&#39;s all about managing risk. If the Product Owner and the team are happy to live with the risk of regressions of bad behaviour then it makes sense to cut down on this automation, or apply it only to critical areas. In most cases this is not the case though, and the only reason releases are approved is because there&#39;s no clear picture of what the certainty is.&lt;br /&gt;
&lt;br /&gt;
Here&#39;s another exercise (more of a challenge really): next time you have to release, create a list of all the acceptance tests in the stories you have already delivered and released. Then try to explain to your Product Owner how many of those have been validated for this release. Feel free to do all the magic and hand waving you want, just stay honest.&lt;br /&gt;
&lt;br /&gt;
You can say &quot;this acceptance test is covered because we have this and this and this unit tests, you see...&quot;, and &quot;this other was tested manually and because it uses most of the same components as acceptance test X then we consider X has also been validated&quot;. This other might also work: &quot;we haven&#39;t touched this component for a long time and because users haven&#39;t complained so far we can safely assume it&#39;s working properly&quot;.&lt;br /&gt;
&lt;br /&gt;
See how much confidence can you get from your Product Owner for that release.&lt;br /&gt;
&lt;br /&gt;
If your application is in any way critical to your company by this point you&#39;ll probably have a very pallid face in front of you. Clear exceptions might be some start-ups, experiments, prototypes, etc.&lt;br /&gt;
&lt;br /&gt;
After perhaps a bit of hatred and arguing, and after pointing out that it&#39;s unfeasible to verify every single acceptance test before each release, this would be the time to propose that you invest in the automation of your acceptance tests, in a production-like environment.&lt;br /&gt;
&lt;br /&gt;
Note that all this is very related to &lt;a href=&quot;http://en.wikipedia.org/wiki/Behavior-driven_development&quot;&gt;BDD&lt;/a&gt;, which has been around for a long time, but most people associate &lt;a href=&quot;http://en.wikipedia.org/wiki/Behavior-driven_development&quot;&gt;BDD&lt;/a&gt; with a framework and it also implies that you write your tests first, which is not the point I&#39;m trying to make here.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Any hints on automating the acceptance tests?&lt;/h2&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Actually, yes, I have a couple of things we&#39;ve been trying and I haven&#39;t seen anywhere else like having a unique set of tests that can be run fast, without any I/O, and also in a full-deployed environment.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Being able to run those tests fast give the developers a very quick feedback on their changes, much like unit tests do, especially if you use a tool like &lt;a href=&quot;http://www.ncrunch.net/&quot;&gt;NCrunch&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The full-deployed version will be much slower so it should probably run as part of your continuos integration, but will give you much more confidence in return.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I&#39;ll try to post more details about this approach soon, but whatever you do, please start being objective about the quality of the software you&#39;re releasing. If you decide to take the step and start to automate your acceptance tests systematically then make sure you invest in quality: you&#39;ll need to maintain this code together with your production code..&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/5389328910097752769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/5389328910097752769' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/5389328910097752769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/5389328910097752769'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2014/05/risk-acceptance-tests-why-unit-tests.html' title='Risk, acceptance tests, why unit tests are not enough, and what can you do about it'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-5002369522479049432</id><published>2014-03-21T11:28:00.000+00:00</published><updated>2017-09-30T10:12:03.473+01:00</updated><title type='text'>Are unit tests waste?</title><content type='html'>[Edit]&lt;br /&gt;
If you&#39;re interested in how to get real confidence out of your investment in testing, see&amp;nbsp;&lt;a href=&quot;http://rodolfograve.blogspot.co.uk/2014/05/risk-acceptance-tests-why-unit-tests.html&quot;&gt;Risk, acceptance tests, why unit tests are not enough, and what can you do about it&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
A co-worker sent me this article from James O Coplien a few days ago: &lt;a href=&quot;http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf&quot;&gt;http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf&lt;/a&gt;.&lt;br /&gt;
If you get past the title (which you should), and don’t take everything it says as “the truth”, there are a lot of interesting things we could take from it. This is my personal resume from the article but I encourage everyone to read it.
&lt;br /&gt;
You can apply many of these personally, other would require team agreement and others would even require changes to wider policies:
&lt;br /&gt;
&lt;div style=&quot;background-color: red;&quot;&gt;
&lt;/div&gt;
&lt;blockquote&gt;
People confuse automated tests with unit tests: so much so that when I criticise unit testing, people rebuke me for critising automation.&lt;/blockquote&gt;
Keep this in mind whilst reading the article (or this resume). This is not about removing automated tests, is about the value of testing one method in isolation (unit) versus testing at the system or sub-system level.&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
(...) don’t forget the Product Owner perspective in Scrum or the business analyst or Program Manager: risk management is squarely in the center of their job, which may be why Jeff Sutherland says that the PO should conceive (and at best design) the system tests as an input to, or during, Sprint Planning (...) Software engineering research has shown that the most cost-effective places to remove bugs are during the transition from analysis and design, in design itself, and in the disciplines of coding. It’s much easier to avoid putting bugs in that to take them out (…) one of my favourite cynical quotes is, “I find that weeks of coding and testing can save me hours of planning.” (...) “There’s something really sloppy about this ‘fail fast’ culture in that it encourages throwing a bunch of pasta at the wall without thinking much… in part due to an over-confidence in the level of risk mitigation that unit tests are achieving”.&lt;/blockquote&gt;
This is said in many other places but you can never say it enough. Translated into process: take your time in the design meetings, don’t rush it and think it through! Do your best to get it right the first time. Don’t leave it to “the QA process” to find your errors later.&lt;br /&gt;
&lt;blockquote&gt;
(...) you can model any program as a Turing tape, and what the program can do is somehow related to the number of bits on that tape at the start of execution. If you want to thoroughly test that program, you need a test with at least the same amount of information: i.e., another Turing tape of at least the same number of bits (…) to do complete testing, the number of lines of code in unit tests would have to be orders of magnitude larger than those in the unit under test (...) Few developers admit that they do only random or partial testing and many will tell you that they do complete testing for some assumed vision of complete. Such visions include notions such as: &quot;Every line of code has been reached,&quot; which, from the perspective of theory of computation, is pure nonsense in terms of knowing whether the code does what it should. Unit tests are unlikely to test more than one trillionth of the functionality of any given method in a reasonable testing cycle. Get over it. (Trillion is not used rhetorically here, but is based on the different possible states given that the average object size is four words, and the conservative estimate that you are using 16-bit words).&lt;/blockquote&gt;
These are some of the reasons why we absolutely need automated Acceptance Tests. It also links to the fact that we shouldn’t care about “impossible” scenarios: if something can’t happen in production then we don’t need to test it, which in turn links back to minimizing configuration options because each option increases the testing effort exponentially.&lt;br /&gt;
&lt;blockquote&gt;
The purpose of testing is to create information about your program. (Testing does not increase quality; programming and design do. Testing just provides the insights that the team lacked to do a correct design and implementation.)&lt;/blockquote&gt;
Never, ever, lose sight of this.&lt;br /&gt;
&lt;blockquote&gt;
The third tests to throw away are the tautological ones. I see more of these than you can imagine — particularly in shops following what they call test-driven development (...) However, as with most unit tests, it’s better to make this an assertion than to pepper your test framework with such checks (...) When I look at most unit tests (...) they are assertions in disguise. When I write a great piece of software I sprinkle it with assertions that describe promises that I expect the callers of my functions to live up to, as well as promises that function makes to its clients. Those assertions evolve in the same artefact as the rest of my code (...) Turn unit tests into assertions. Use them to feed your fault-tolerance architecture on high-availability systems. This solves the problem of maintaining a lot of extra software modules that assess execution and check for correct behavior; that’s one half of a unit test. The other half is the driver that executes the code: count on your stress tests, integration tests, and system tests to do that.&lt;/blockquote&gt;
This is what Code Contracts should be doing for us. Unfortunately Code Contracts seems to be taking too long to become a finished product but if you choose to get rid of it then you should at least replace the contracts with Debug.Assert.&lt;br /&gt;
&lt;blockquote&gt;
(...) one question to ask about every test is: If this test fails, what business requirement is compromised? Most of the time, the answer is, &quot;I don&#39;t know.&quot; If you don&#39;t know the value of the test, then the test theoretically could have zero business value. The test does have a cost: maintenance, computing time, administration, and so forth. That means the test could have net negative value.&lt;/blockquote&gt;
Make sure you link your automated acceptance tests back to the original acceptance test which in turn should be linked to a requirement (User Story, Use Case, etc). If you&#39;re using some BDD framework then you might have the option to consider the automated tests as your actual acceptance tests.&lt;br /&gt;
&lt;blockquote&gt;
If you cannot tell how a unit test failure contributes to product risk, you should evaluate whether to throw the test away. There are better techniques to attack quality lapses in the absence of formal correctness criteria, such as exploratory testing and Monte Carlo techniques. (Those are great and I view them as being in a category separate from what I am addressing here.) Don’t use unit tests for such validation.&lt;/blockquote&gt;
Again, Acceptance vs Unit Tests. They aren’t the same and Acceptance Tests that link directly to requirements provide much more value.&lt;br /&gt;
&lt;blockquote&gt;
Most programmers believe that source line coverage, or at least branch coverage, is enough. No. From the perspective of computing theory, worst-case coverage means investigating every possible combination of machine language sequences, ensuring that each instruction is reached, and proving that you have reproduced every possible configuration of bits of data in the program at every value of the program counter. (It is insufficient to reproduce the state space for just the module or class containing the function or method under test: generally, any change anywhere can show up anywhere else in a program and requires that the entire program can be retested. Long fragment but very interesting. This is why we need to minimize the number of interactions in a system.&lt;/blockquote&gt;
Even if “in general” his explanation seems correct, a good design can (and should) mitigate this by applying encapsulation, SRP, cohesion, preferring immutable state when possible, etc. Make each module in the system be a black-box API to other modules, and define the interaction with well-defined contracts.&lt;br /&gt;
&lt;blockquote&gt;
(...) The classes he was testing are code. The tests are code. Developers write code. When developers write code they insert about three system-affecting bugs per thousand lines of code. If we randomly seed my client’s code base — which includes the tests — with such bugs, we find that the tests will hold the code to an incorrect result more often than a genuine bug will cause the code to fail! Interesting point.&lt;/blockquote&gt;
The numbers are clear but I believe he’s not considering that tests should be much simpler than “production code”, so the bug ratio must be much lower (the number of bugs is not a linear function of the complexity but exponential or similar).&lt;br /&gt;
&lt;blockquote&gt;
Create system tests with good feature coverage (not code coverage) — remembering that proper response to bad inputs or other unanticipated conditions is part of your feature set.&lt;/blockquote&gt;
No comments. Just do it.&lt;br /&gt;
In summary (from the article itself, not my words. &lt;b&gt;Bold&lt;/b&gt; means I consider it controversial, the rest I consider we should be doing it):
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Keep regression tests around &lt;b&gt;for up to a year&lt;/b&gt; — but most of those will be system-level tests rather than unit tests.&lt;/li&gt;
&lt;li&gt;Keep unit tests that test key algorithms for which there is a broad, formal, independent oracle of correctness, and for which there is ascribable business value.&lt;/li&gt;
&lt;li&gt;Except for the preceding case, if X has business value and you can test X with either a system test or a unit test, &lt;b&gt;use a system test&lt;/b&gt; — context is everything. &lt;i&gt;I understand he’s using “unit tests” referring to the scope (1 method). Speed is a different concern here.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;Design a test with more care than you design the code.&lt;/li&gt;
&lt;li&gt;Turn most unit tests into assertions.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Throw away tests that haven’t failed in a year.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Testing can’t replace good development: a high test failure rate suggests you should shorten development intervals, perhaps radically, and make sure your architecture and design regimens have teeth.&lt;/li&gt;
&lt;li&gt;If you find that individual functions being tested are trivial, double-check the way you incentivize developers’ performance. Rewarding coverage or other meaningless metrics can lead to rapid architecture decay.&lt;/li&gt;
&lt;li&gt;Be humble about what tests can achieve. Tests don’t improve quality: developers do.&lt;/li&gt;
&lt;/ol&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/5002369522479049432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/5002369522479049432' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/5002369522479049432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/5002369522479049432'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2014/03/are-unit-tests-waste.html' title='Are unit tests waste?'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-7881400466112719724</id><published>2013-04-16T12:56:00.002+01:00</published><updated>2013-04-26T09:53:02.465+01:00</updated><title type='text'>NuGet.Server + IIS 7.5: nuget push returns 404 error with large packages</title><content type='html'>After installing a NuGet server using the NuGet.Server package I was getting 404 error when trying to push packages:&lt;br /&gt;
&lt;br/&gt;
F:\test&amp;gt;NuGet.exe push MyPackage.1.0.0.0.nupkg -Source http://nugetrepo/ -ApiKey myApiKey&lt;br /&gt;
&lt;br /&gt;
Pushing MyPackage 1.0.0.0 to &#39;http://nugetrepo:81/&#39;...&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: red;&quot;&gt;Failed to process request. &#39;Not Found&#39;.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: red;&quot;&gt;The remote server returned an error: (404) Not Found..&lt;/span&gt;&lt;br /&gt;
&lt;br/&gt;
&lt;h3&gt;
Short version&lt;/h3&gt;
The cause in my case was that the package was too big. If your package is moderately large you need to set the maxAllowedContentLength setting to a larger number:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;system.webserver&amp;gt;&lt;br /&gt;
&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;lt;security&amp;gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;requestFiltering&amp;gt;&amp;nbsp;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;requestLimits maxAllowedContentLength=&quot;32212254720&quot;&amp;gt;&amp;nbsp;&amp;lt;/requestLimits&amp;gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;/requestFiltering&amp;gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&amp;lt;/system.webserver&amp;gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
This setting controls the biggest file size accepted by IIS. Notice this setting is specified in bytes.&lt;br /&gt;
&lt;br /&gt;
You also need to set ASP.NET&#39;s maxRequestLength setting to a corresponding large number (this time in Kb):&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&amp;lt;system.web&amp;gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;lt;httpRuntime maxRequestLength=&quot;31457280&quot; targetFramework=&quot;4.5&quot;&amp;gt;&amp;lt/httpRuntime&amp;gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&amp;lt;/system.web&amp;gt;&lt;/i&gt;&lt;br /&gt;
&lt;br/&gt;
&lt;h3&gt;
Full version&lt;/h3&gt;
Obvious things discarded (wrong api key, wrong URL, server not available, etc) I then turned to Fiddler. 2 requests are made by the NuGet.exe client:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;The first one a GET to the site root (http://nugetrepo). This is sucessful.&lt;/li&gt;
&lt;li&gt;A subsequent PUT to http://nugetrepo/api/v2/package which fails with a 404 error.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
I went on and enabled IIS Failed Request Tracing (see &lt;a href=&quot;http://www.iis.net/learn/troubleshoot/using-failed-request-tracing/troubleshooting-failed-requests-using-tracing-in-iis&quot;&gt;here&lt;/a&gt;) which gave me the key piece of information: the error was a 404.13. For some reason I didn&#39;t see that 404.13 on Fiddler.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Once I knew the cause it was fairly straight forward to find the solution.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Hope this helps! It will certainly help myself in the future.&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/7881400466112719724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/7881400466112719724' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/7881400466112719724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/7881400466112719724'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2013/04/nugetserver-iis-75-nuget-push-returns.html' title='NuGet.Server + IIS 7.5: nuget push returns 404 error with large packages'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-6428257991551493669</id><published>2013-03-11T23:45:00.000+00:00</published><updated>2013-03-11T23:57:04.572+00:00</updated><title type='text'>TEAM.BabyHost: leave your baby playing in the PC</title><content type='html'>&lt;br /&gt;
&lt;h3&gt;
TEAM.BabyHost&lt;/h3&gt;
If you ever wanted to leave your baby or toddler playing some game in the computer without fearing he will inadvertently (sometimes I doubt it!) do nasty things, like closing all your other windows, open every possible &amp;nbsp;application and discovering all kind of keyboard shorcuts you had never imagined existed:&lt;br /&gt;
&lt;h4&gt;
&lt;/h4&gt;
&lt;br /&gt;
&lt;h4&gt;
TEAM.BabyHost is your friend&lt;/h4&gt;
TEAM.BabyHost lets you open any web page in a controlled sandbox. With so many flash games already available you just need to navigate to the web page or point it to a local flash file.&lt;br /&gt;
&lt;br /&gt;
Get your copy &lt;a href=&quot;https://bitbucket.org/rodolfograve/team.babyhost/downloads/TEAM.BabyHost.exe&quot;&gt;here in bitbucket&lt;/a&gt;.&lt;br /&gt;
&lt;h4&gt;
&lt;/h4&gt;
&lt;br /&gt;
&lt;h4&gt;
How does it work?&lt;/h4&gt;
TEAM.BabyHost is a full screen application which intercepts most of the special keyboard shortcuts available in Windows applications. In fact, it can intercept all shortcuts except for Ctrl+Alt+del and Windows+L. Those might be coming in the future though so if you like the application stay tuned.&lt;br /&gt;
&lt;br /&gt;
As a full-screen application it prevents babies from using the mouse outside of the window too!&lt;br /&gt;
&lt;h4&gt;
&lt;/h4&gt;
&lt;h4&gt;
How does it look?&lt;/h4&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieNDs2_yPIXRVAxt5F0K2tZD8rm4yncBNvy61zdghdQ8XqR4-3x-C25e7flA4FAsWxge5DpxWaS-8c8iGtENd64-4BXsM-RAAPLCULX7XfcUBoqsMV8VICqM45lzZUrdHq-S7tqfQ7XvU/s1600/Screenshot-NotPlaying.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;339&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieNDs2_yPIXRVAxt5F0K2tZD8rm4yncBNvy61zdghdQ8XqR4-3x-C25e7flA4FAsWxge5DpxWaS-8c8iGtENd64-4BXsM-RAAPLCULX7XfcUBoqsMV8VICqM45lzZUrdHq-S7tqfQ7XvU/s640/Screenshot-NotPlaying.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Feedback&lt;/h4&gt;
Your feedback is very welcome. Get in touch by sending an email to rodolfograve@gmail.com, by leaving a comment here or by creating an issue in &lt;a href=&quot;https://bitbucket.org/rodolfograve/team.babyhost/issues?status=new&amp;amp;status=open&quot;&gt;bitbucket&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/6428257991551493669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/6428257991551493669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/6428257991551493669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/6428257991551493669'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2013/03/teambabyhost-leave-your-baby-playing-on.html' title='TEAM.BabyHost: leave your baby playing in the PC'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieNDs2_yPIXRVAxt5F0K2tZD8rm4yncBNvy61zdghdQ8XqR4-3x-C25e7flA4FAsWxge5DpxWaS-8c8iGtENd64-4BXsM-RAAPLCULX7XfcUBoqsMV8VICqM45lzZUrdHq-S7tqfQ7XvU/s72-c/Screenshot-NotPlaying.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-986346397953260615</id><published>2013-03-11T22:37:00.000+00:00</published><updated>2013-03-11T22:55:18.509+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="Patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="Single Action Controllers"/><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><title type='text'>Single Action Controller: more improvements</title><content type='html'>It&#39;s been more than a year since the last entry and I&#39;ve done more improvements to the implementation of Single Action Controller in &lt;a href=&quot;http://nuget.org/packages/TEAM.Commons.Web&quot;&gt;TEAM.Commons.Web&lt;/a&gt;.

Most of the improvements have been around removing magic strings and using types instead.&lt;br /&gt;
&lt;br /&gt;
The following gist shows some examples of what you get:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/rodolfograve/5138291.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
If you like type safety and finding errors at compile time rather than build time, you&#39;re going to love this approach, together with &lt;a href=&quot;http://blogs.msdn.com/b/jimlamb/archive/2010/04/20/turn-on-compile-time-view-checking-for-asp-net-mvc-projects-in-tfs-build-2010.aspx&quot;&gt;enabling view compilation&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
On top of that I&#39;ve also added some methods to help with testing of applications built with this library. This is how you verify that an action returns a View:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/rodolfograve/5138436.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
And this is how you check that an action returns a redirect to another Single Action Controller:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/rodolfograve/5138468.js&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/986346397953260615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/986346397953260615' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/986346397953260615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/986346397953260615'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2013/03/single-action-controller-more.html' title='Single Action Controller: more improvements'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-6179678238243892391</id><published>2012-01-29T12:34:00.001+00:00</published><updated>2013-03-11T22:55:34.585+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="Patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="Single Action Controllers"/><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><title type='text'>Single Action Controller - Take 2</title><content type='html'>&lt;p&gt;After almost a year of using the first version of Single Action Controllers over the ASP.NET MVC (&lt;a href=&quot;http://rodolfograve.blogspot.com/2011/05/teamcommons-mvc-single-responsibility.html&quot;&gt;http://rodolfograve.blogspot.com/2011/05/teamcommons-mvc-single-responsibility.html&lt;/a&gt;), I have applied a few improvements on it. I particularly didn&#39;t like the requirement to inherit from a custom class (SingleActionController), and the boilerplate code required in your Global.asax.&lt;/p&gt;
&lt;p&gt;
So, the current implementation (also available as a NuGet package at &lt;a href=&quot;http://nuget.org/packages/TEAM.Commons.Web&quot;&gt;http://nuget.org/packages/TEAM.Commons.Web&lt;/a&gt;) doesn&#39;t require your controller class to inherit from SingleActionController but from the usual Controller class, and provides a helper method for Autofac users:&lt;/p&gt;

&lt;p&gt;Global.asax:
&lt;pre class=&quot;brush: csharp&quot;&gt;protected void Application_Start()
{
  var builder = new ContainerBuilder();

  // Register your dependencies

  builder.RegisterTypesForSingleActionControllers(Assembly.GetExecutingAssembly(), &quot;Base namespace of your controllers&quot;);
}
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
A controller:
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;using MyCompany.MyProject.ViewModels.Author;

// Name your namespace after your controller.
// This works very nicely with the directory structure you create in your project.
namespace MyCompany.MyProject.Controllers.Author
{
  // Name your class after your Action and make it inherit from the standard Controller
  public class Index : Controller
  {
    // One single action named Execute
    public ActionResult Execute(FilterDataModel filter) { ... }
  }
}
&lt;/pre&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/6179678238243892391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/6179678238243892391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/6179678238243892391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/6179678238243892391'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2012/01/single-action-controller-take-2.html' title='Single Action Controller - Take 2'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-1068808528949480288</id><published>2011-05-14T17:27:00.000+01:00</published><updated>2013-03-11T22:55:50.839+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="Patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="Single Action Controllers"/><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><title type='text'>TEAM.Commons: MVC + Single Responsibility Principle (SRP) = Single Action Controller</title><content type='html'>&lt;p&gt;Since a long time ago I&#39;ve been concerned about the increasing size and complexity of our ASP.NET MVC controllers: we have been clearly going against the Single Responsibility Principle.&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;UPDATE: &lt;/h2&gt;an improved version of this implementation is available &lt;a href=&quot;http://rodolfograve.blogspot.com/2012/01/single-action-controller-take-2.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Common controllers&lt;/h2&gt;
&lt;p&gt;This is some sample code to illustrate how one of our typical controllers looked like:&lt;/p&gt;
&lt;p&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;using MyCompany.MyProject.Models.Author;

namespace TEAM.MvcSACDemo.WebUI.Controllers
{

  public class AuthorsController : Controller
  {

    // Dependencies (smell: too many dependencies)
    protected readonly IDbSessionFactory DbSessionFactory;
    protected readonly IIndexQueries IndexQueries;
    protected readonly IEditQueries EditQueries;

    // Actions
    // Smells: too many methods; too many qualifications in the classes&#39; names)
    public ActionResult Index(AuthorsFilterDataModel filter) { ... }

    public ActionResult Create() { ... }

    public ActionResult Insert(AuthorInsertDataModel newAuthor) { ... }

    public ActionResult Edit(long id) { ... }

    public ActionResult Update(AuthorUpdateDataModel) { ... }
  }
}
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;The violation of the Single Responsibility Principle should be obvious.&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;Our new approach&lt;/h2&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;My initial thought was to change the rule we have been using to create a controller, which is &lt;b&gt;one controller per entity&lt;/b&gt;, and find some other rule that produces more controllers with less actions while keeping or increasing the organization level.&lt;/p&gt;
&lt;p&gt;A few days ago I stumbled on &lt;a href=&quot;http://feedproxy.google.com/~r/LosTechies/~3/KgddCzmy-98/single-action-controllers-with-asp-net-mvc&quot;&gt;this post&lt;/a&gt; by Derek Greer, and immediately asked my friend Yaniel Díaz help me to develop this idea. After a couple of iterations we had a couple of classes and extension methods that will let us (and also you if you like) implement Single Action Controllers keeping must of the nice ASP.NET MVC conventions.&lt;/p&gt;
&lt;p&gt;First, let&#39;s see how do Single Action Controllers look like:&lt;/p&gt;
&lt;p&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;using MyCompany.MyProject.Models.Author.Index;

// Name your namespace after your controller.
// This works very nicely with the directory structure you create in your project.
namespace TEAM.MvcSACDemo.Controllers.Author
{
  // Name your class after your Action and inherit from SingleActionController
  // You could choose to name it IndexAction instead
  public class Index : SingleActionController
  {
    // Only one dependency
    protected readonly IIndexQueries IndexQueries;

    // One single action (notice the use of namespace to remove extra qualification in the classes&#39; names)
    public ActionResult Execute(FilterDataModel filter) { ... }
  }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And this is how it all looks in the Solution Explorer:&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0H12Sgo_hryaRdADVGVfTA2t258ebbiOvJ1Vs6uQBGa-LcdL7INw_SE6rN8deBxk-X9iuwrFwjEl55AUKE1HvDAwFgv9OkrYhFPtnAj4sbKzQeBO2f9gkNO8h5ECMeHDvlRXUd78nxQA/s1600/TEAM.MvcSACSolution.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; width=&quot;151&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0H12Sgo_hryaRdADVGVfTA2t258ebbiOvJ1Vs6uQBGa-LcdL7INw_SE6rN8deBxk-X9iuwrFwjEl55AUKE1HvDAwFgv9OkrYhFPtnAj4sbKzQeBO2f9gkNO8h5ECMeHDvlRXUd78nxQA/s320/TEAM.MvcSACSolution.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Except for the &quot;Author&quot; and &quot;OtherEntity&quot; nested folders, it&#39;s all like &quot;traditional&quot; MVC.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Using it in your application&lt;/h2&gt;&lt;br /&gt;
All the required classes are available in the &lt;a href=&quot;https://bitbucket.org/rodolfograve/team.commons&quot;&gt;TEAM.Commons&lt;/a&gt; package under the &lt;a href=&quot;https://bitbucket.org/rodolfograve/team.commons/src/f2d2a538bfcc/TEAM.Commons.Web/MVC/&quot;&gt;TEAM.Commons.Web.MVC.SingleActionControllers&lt;/a&gt; namespace. TEAM.Commons is also available as a &lt;a href=&quot;http://nuget.org/List/Packages/TEAM.Commons&quot;&gt;NuGet package&lt;/a&gt;, which is the preferred way to share code these days.&lt;br /&gt;
&lt;br /&gt;
After you install TEAM.Commons in your solution (or copy the code you need), you must register your routes using the custom SingleActionControllerRoute:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public static void RegisterRoutes(RouteCollection routes)
{
  routes.IgnoreRoute(&quot;{resource}.axd/{*pathInfo}&quot;);
  // Best practice to avoid MVC handling the favicon request
  routes.IgnoreRoute(&quot;{*favicon}&quot;, new { favicon = @&quot;(.*/)?favicon.ico(/.*)?&quot; });

  // Only change the original MapRoute by our MapSingleActionControllersRoute
  routes.MapSingleActionControllersRoute(
    &quot;Default&quot;,
    &quot;{controller}/{action}/{id}&quot;,
    new { controller = &quot;Author&quot;, action = &quot;Index&quot;, id = UrlParameter.Optional },
    new { }
  );
}
&lt;/pre&gt;&lt;br /&gt;
and then register SingleActionControllersFactory as the ControllerFactory:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;// You must pass the fully qualified name of the assembly
// and the namespace of the controllers. 
// In future versions we&#39;ll simplify this step.
ControllerBuilder.Current.SetControllerFactory(new SingleActionControllerFactory(Assembly.GetExecutingAssembly().FullName, &quot;TEAM.MvcSACDemo.Controllers&quot;));
&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;The internals&lt;/h2&gt;&lt;br /&gt;
Thanks to ASP.NET MVC design we just had to implement a custom ControllerFactory, a custom Route  and a custom base class for controllers.&lt;br /&gt;
&lt;br /&gt;
Check the source code at the &lt;a href=&quot;https://bitbucket.org/rodolfograve/team.commons/src/f2d2a538bfcc/TEAM.Commons.Web/MVC/&quot;&gt;TEAM.Commons repository&lt;/a&gt;. It should be self-explanatory and could give you ideas about how to do it yourself in case you don&#39;t want to use TEAM.Commons.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;&lt;br /&gt;
The implemented solution is not perfect and I&#39;m sure it could be improved, but we needed to go back to SRP in our controllers as soon as possible. I&#39;ll update this post when we find a new solution.&lt;br /&gt;
&lt;br /&gt;
I hope you find this as useful as we do :-)</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/1068808528949480288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/1068808528949480288' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/1068808528949480288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/1068808528949480288'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2011/05/teamcommons-mvc-single-responsibility.html' title='TEAM.Commons: MVC + Single Responsibility Principle (SRP) = Single Action Controller'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0H12Sgo_hryaRdADVGVfTA2t258ebbiOvJ1Vs6uQBGa-LcdL7INw_SE6rN8deBxk-X9iuwrFwjEl55AUKE1HvDAwFgv9OkrYhFPtnAj4sbKzQeBO2f9gkNO8h5ECMeHDvlRXUd78nxQA/s72-c/TEAM.MvcSACSolution.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-1667775646267965808</id><published>2011-03-25T15:58:00.000+00:00</published><updated>2011-03-25T15:58:16.451+00:00</updated><title type='text'>Unobtrusive and useful Google Chrome plugins for developers</title><content type='html'>There are zillions of plugins for Google Chrome, and several of them are developer-oriented. However, some of these plugins interrupt my usual workflow, or make Chrome slow and unresponsive, or are simply not well tested and crash.&lt;br /&gt;
&lt;br /&gt;
These are the plugins I&#39;ve found to be more useful:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://getfirebug.com/releases/lite/chrome/&quot;&gt;FireBug Light&lt;/a&gt; (as good as in FireFox).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrome.google.com/extensions/detail/cpngackimfmofbokmjmljamhdncknpmg&quot;&gt;Screen Capture - by Google&lt;/a&gt; (there are many screen capture plugins, I just picked this one)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrome.google.com/extensions/detail/idhfcdbheobinplaamokffboaccidbal&quot;&gt;Resolution Test&lt;/a&gt; (another classic, very useful)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrome.google.com/extensions/detail/kmgmkbicahmbceidoidjbkbpkfogaldh&quot;&gt;jsshell&lt;/a&gt; (Amazing for testing javascript and jQuery)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/dgchjemniofpmdkgnoejdkgomjldfgmh&quot;&gt;Magic Inputs Filler&lt;/a&gt; (saves a lot of time of filling forms for testing).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/ggfgijbpiheegefliciemofobhmofgce&quot;&gt;CSSViewer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/fhjcajmcbmldlhcimfajhfbgofnpcjmb&quot;&gt;Simple REST client&lt;/a&gt; (Build custom HTTP request to test your services)&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/1667775646267965808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/1667775646267965808' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/1667775646267965808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/1667775646267965808'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2011/03/unobtrusive-and-useful-google-chrome.html' title='Unobtrusive and useful Google Chrome plugins for developers'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-7278160509876390358</id><published>2011-03-21T20:10:00.000+00:00</published><updated>2011-03-21T20:10:41.556+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><title type='text'>TEAM.Commons published as a NuGet Package</title><content type='html'>&lt;a href=&quot;http://nuget.codeplex.com/&quot;&gt;NuGet&lt;/a&gt; is a nice tool to share code (source or compiled).&lt;br /&gt;
&lt;br /&gt;
I&#39;ve published &lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&quot;&gt;TEAM.Commons&lt;/a&gt; as a NuGet package in &lt;a href=&quot;http://nuget.org/List/Packages/TEAM.Commons&quot;&gt;http://nuget.org/List/Packages/TEAM.Commons&lt;/a&gt;. With this step it&#39;s much easier to use this set of classes: just type Install-Package TEAM.Commons in your NuGet console.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/7278160509876390358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/7278160509876390358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/7278160509876390358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/7278160509876390358'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2011/03/teamcommons-published-as-nuget-package.html' title='TEAM.Commons published as a NuGet Package'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-758815790945020968</id><published>2011-03-12T15:07:00.002+00:00</published><updated>2011-03-12T15:09:13.248+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="My Applications"/><category scheme="http://www.blogger.com/atom/ns#" term="Patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="Unobtrusive"/><title type='text'>Unobtrusive jQuery UI (jquery.ui.unobtrusive)</title><content type='html'>I am very enthusiastic about unobtrusive JavaScript. It&#39;s a design pattern and usual warnings apply:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;It doesn&#39;t apply to every scenario.&lt;/li&gt;
&lt;li&gt;It will hurt if you use it wrong.&lt;/li&gt;
&lt;li&gt;Long etc.&lt;/li&gt;
&lt;/ul&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Very short version of this post&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I hope someone creates a complete jquery.ui.unobtrusive plugin. Since I&#39;m a developer I have already started one at:&lt;br /&gt;
&lt;a href=&quot;https://bitbucket.org/rodolfograve/jquery.ui.unobtrusive&quot;&gt;https://bitbucket.org/rodolfograve/jquery.ui.unobtrusive&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The bad news is that I&#39;m not an expert JavaScript nor jQuery developer, so I&#39;m sure the quality of what I&#39;m doing can be greatly improved. It will be great if someone with more expertise could continue this work or start his own and make it public.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Long version&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I think unobtrusive JavaScript solves several old and current problems:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;How do we make advanced HTML + JavaScript stuff from server-side code?&lt;/li&gt;
&lt;li&gt;How do we reuse JavaScript code that interacts with the elements of a page?&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Until now I&#39;ve seen incomplete and ugly approaches (the latter is obviously a personal opinion):&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Don&#39;t do advanced HTML + JavaScript from server-side code at all and create custom JavaScript code for each page you have.&lt;/li&gt;
&lt;li&gt;Generate small pieces of script from server-side code, intermingled with the final HTML code (outside the head tag), and handle elements&#39; IDs and classes.&lt;/li&gt;
&lt;/ul&gt;With unobtrusive JavaScript we have a new great approach: generate HTML attributes in your tags and let your unobtrusive scripts do their science (I appreciate science more than magic).&lt;br /&gt;
&lt;br /&gt;
This new approach is:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Flexible: you can use whatever you like to generate the attributes (ASP.NET MVC HtmlHelpers, your own framework, write attributes by hand in your HTML, etc).&lt;/li&gt;
&lt;li&gt;Testable: unobtrusive scripts can (or even must) be developed as reusable components, with their own tests (&lt;a href=&quot;http://blogs.msdn.com/b/simonince/archive/2011/02/28/javascript-architecture.aspx&quot;&gt;JavaScript as a Framework&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Readable:&amp;nbsp;your HTML code will declaratively express what it does (no need to look IDs nor classes in JavaScript files).&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;No more &lt;b&gt;obscure&lt;/b&gt; separation between the appearance and the behavior. This separation is good and encouraged, but it&#39;s much better without the &quot;obscure&quot; feature added by current implementations (you must look your IDs or CSS classes in your JavaScript code to know what&#39;s going on with an HTML element).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
  $(document).ready(function() {
    $(&quot;myDatePicker&quot;).datepicker({
      showOn: &quot;button&quot;,
      buttonImage: &quot;../themes/mytheme/calendar.gif&quot;
    });
  });Notice this piece of script usually is in another file (even worst).
&amp;lt;/script&amp;gt;
  &amp;lt;/head&amp;gt;
  
  Lots of stuff, and then hidden some where in the page:

  &amp;lt;input id=&quot;myDatePicker&quot; name=&quot;myDatePicker&quot; type=&quot;text&quot; &amp;gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;With unobtrusive JavaScript you keep the separation at the implementation level, and avoid the separation at the code level.&lt;/div&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;input type=&quot;text&quot; ui-datepicker=&quot;true&quot; ui-datepicker-showOn=&quot;button&quot;
                                             ui-datepicker-buttonImage=&quot;../themes/mytheme/calendar.gif&quot; &amp;gt;
&lt;/pre&gt;&lt;br /&gt;
This last code looks much better to me and I wish we soon have the unobtrusive &quot;mapper&quot; of the most popular JavaScript frameworks out there.&lt;br /&gt;
&lt;br /&gt;
What do you think?</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/758815790945020968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/758815790945020968' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/758815790945020968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/758815790945020968'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2011/03/unobtrusive-jquery-ui.html' title='Unobtrusive jQuery UI (jquery.ui.unobtrusive)'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-5503989443814508927</id><published>2010-09-18T12:13:00.005+01:00</published><updated>2010-10-19T21:48:15.681+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Parallelization"/><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><category scheme="http://www.blogger.com/atom/ns#" term="Threading"/><title type='text'>TEAM.Commons: Messaging</title><content type='html'>This is the 6th of several posts about TEAM.Common, a set of functionality I use in every project and that I&#39;d like to share. The index is here: &lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&quot;&gt;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Before talking about the details of TEAM.Commons.Threading I need to explain TEAM.Commons.Messaging, a set of classes about communication between processes based on the concept of &lt;i&gt;transport&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Messaging/ISendingTransport.cs&quot;&gt;ISendingTransport&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public interface ISendingTransport
{
    void Send(object message);
    void Send(object[] messages);
}
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Messaging/IReceivingTransport.cs&quot;&gt;IReceivingTransport&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public interface IReceivingTransport
{
    // Blocks the current thread until a message is received.
    IList&amp;lt;object&amp;gt; WaitForMessageWithoutTimeout();

    /// Blocks the current thread until a message is received or timeout ellapses.
    IList&amp;lt;object&amp;gt; WaitForMessage(TimeSpan timeout);
}
&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;
There are two available implementations of these transports:&lt;br /&gt;
&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Messaging/InProcessTransport.cs&quot;&gt;InProcessTransport&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public class InProcessTransport : ISendingTransport, IReceivingTransport
{
...
}
&lt;/pre&gt;This class implements both interfaces so that it can be used for communications between threads, handling all the related complexity. It&#39;s a very important piece used in the implementation of the advanced threading features in TEAM.Commons.Threading.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Messaging/MsmqSendingTransport.cs&quot;&gt;MsmqSendingTransport&lt;/a&gt;&lt;br /&gt;
Send messages through an MSMQ Queue.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Messaging/MsmqReceivingTransport.cs&quot;&gt;MsmqReceivingTransport&lt;/a&gt;&lt;br /&gt;
Receives messages from an MSMQ Queue.&lt;br /&gt;
&lt;/p&gt;&lt;br /&gt;
Remember, you can get all this code for free at bitbucket: &lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/overview&quot;&gt;http://bitbucket.org/rodolfograve/team.commons/overview&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Check it out to get ideas, or simply use it as it is. It&#39;s working out for me and my team.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/5503989443814508927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/5503989443814508927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/5503989443814508927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/5503989443814508927'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2010/09/teamcommons-messaging-before-threading.html' title='TEAM.Commons: Messaging'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-5767598074607701995</id><published>2010-09-18T11:24:00.086+01:00</published><updated>2010-10-19T21:48:58.289+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><title type='text'>TEAM.Commons: Threading - part 2</title><content type='html'>This is the 5th of several posts about TEAM.Common, a set of functionality I use in every project and that I&#39;d like to share. The index is here: &lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&quot;&gt;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
In TEAM.Common.Threading you can find these abstractions:&lt;br /&gt;
&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Commons.Threading/WorkerThread.cs&quot;&gt;WorkerThread&lt;/a&gt;&lt;br /&gt;
A thread running a task in an &quot;infinite&quot; loop, until some other thread asks it to stop.&lt;br /&gt;
This is a very basic piece I use it all the time for implementing services and it&#39;s also the foundation for the &quot;advanced&quot; features.&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public abstract class WorkerThread
{
 Exception Error { get; }
 void ForceStop();
 bool IsStopped { get; }
 void Start();
 void Stop();
 event EventHandler&amp;lt;System.ComponentModel.RunWorkerCompletedEventArgs&amp;gt; Stopped;
}
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Commons.Threading/ProducerConsumersProcess.cs&quot;&gt;ProducerConsumersProcess&lt;/a&gt;&lt;br /&gt;
My approach to parallelization was to use the &lt;a href=&quot;http://en.wikipedia.org/wiki/Producer-consumer_problem&quot;&gt;one producer -&gt; several consumers&lt;/a&gt; technique:&lt;br /&gt;
You must create an instance of this class passing an instance of IProducer and a list of IConsumerWorker.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public class ProducerConsumersProcess&amp;lt;T&amp;gt;
{
    int ConsumedItemsCount { get; }
    int ProducedItemsCount { get; }
    void Start();
}
&lt;/pre&gt;&lt;br /&gt;
With a very simple interface, ProducerConsumersProcess&amp;lt;T&amp;gt; coordinates the producer and the consumers using a buffer (an &lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-messaging-before-threading.html&quot;&gt;InProcessTransport&lt;/a&gt;, see &lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-messaging-before-threading.html&quot;&gt;next post&lt;/a&gt;) and handling a lot of edge cases and exceptions.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Commons.Threading/IProducer.cs&quot;&gt;IProducer&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public interface IProducer&amp;lt;T&amp;gt;
{
    T ProduceOne();
    bool HasFinished();
}
&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Commons.Threading/IConsumerWorker.cs&quot;&gt;IConsumerWorker&amp;lt;T&amp;gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public interface IConsumerWorker&amp;lt;T&amp;gt;
{
    event EventHandler&amp;lt;RunWorkerCompletedEventArgs&amp;gt; Stopped;
    void Start(IReceivingTransport receivingTransport);
    void StopWhenStarved();
    void InterruptExecution();
    bool IsStopped { get; }
    int ProcessedItemsCount { get; }
    Exception Error { get; }
    string Id { get; }
}
&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;
These are the foundations for all the good stuff. The rest are classes that help in the most common cases:&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Commons.Threading/DelegatedProducer.cs&quot;&gt;DelegatedProducer&amp;lt;T&amp;gt;&lt;/a&gt;&lt;br /&gt;
Just pass two delegates:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public DelegatedProducer(Func&amp;lt;T&amp;gt; producerDelegate, Func&amp;lt;bool&amp;gt; hasFinishedDelegate)&lt;/pre&gt;Combine it with lambda expressions and you have a very flexible and expressive syntax.&lt;br /&gt;
&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Commons.Threading/EnumeratorProducer.cs&quot;&gt;EnumeratorProducer&amp;lt;T&amp;gt;&lt;/a&gt;&lt;br /&gt;
Just pass an IEnumerable:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public EnumeratorProducer(IEnumerable&amp;lt;T&amp;gt; enumerableSource)&lt;/pre&gt;Combine it with the &lt;i&gt;yield&lt;/i&gt; operator and/or lambda expressions and again, you have a very flexible and expressive syntax.&lt;br /&gt;
&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Commons.Threading/EnumeratorProducer.cs&quot;&gt;EnumeratorProducer&amp;lt;T&amp;gt;&lt;/a&gt;&lt;br /&gt;
Just pass an IEnumerable:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public DelegatedConsumerWorker(string id, TimeSpan starvationTimeOut, int processedItemsCountMonitorizationStep, Action&amp;lt;T&amp;gt; consumerDelegate)&lt;/pre&gt;You know what comes now: mix it with lambda expressions and...&lt;/p&gt;&lt;br /&gt;
Remember, you can get all this code for free at bitbucket: &lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/overview&quot;&gt;http://bitbucket.org/rodolfograve/team.commons/overview&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Check it out to get ideas, or simply use it as it is. It&#39;s working out for me and my team.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/5767598074607701995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/5767598074607701995' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/5767598074607701995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/5767598074607701995'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2010/09/teamcommons-threading-part-2.html' title='TEAM.Commons: Threading - part 2'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-3199388266563352543</id><published>2010-09-18T11:17:00.003+01:00</published><updated>2010-10-19T21:48:58.291+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><title type='text'>TEAM.Commons: Threading - part 1</title><content type='html'>This is the 4th of several posts about TEAM.Common, a set of functionality I use in every project and that I&#39;d like to share. The index is here: &lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&quot;&gt;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
(Multi)Threading is a complex, error prone task. You must take a lot of details into account everytime you&#39;re going to do it. On the other side, it&#39;s a very powerful tool and refusing to use it is not a valid solution. At least not if you want to do some large processings or interactive UIs.&lt;br /&gt;
&lt;br /&gt;
AJAX (web), BackgroundWorker and Dispatcher (desktop), have solved the interactive UIs part (at least I feel comfortable enough with those these days), but I didn&#39;t feel the same about large processings that could be parallelized.&lt;br /&gt;
&lt;br /&gt;
At some point I got tired of avoiding multithreading until there was no other option and got my self to implement some abstractions that would allow me and my team to implement parallel processes really, really quickly, with industry level robustness.&lt;br /&gt;
&lt;br /&gt;
The result is &lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/src/tip/TEAM.Commons.Threading&quot;&gt;TEAM.Commons.Threading&lt;/a&gt;. Next thing is an example so that you can decide if you like it and want to go on reading this post, or stop right here.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;// Create the list of consumers... we are creating 5 consumers for this example
var consumers = Enumerable.Range(1, 5).Select(x =&amp;gt;
        new DelegatedConsumerWorker&amp;lt;string&amp;gt;(
            &amp;quot;Consumer&amp;quot; + x.ToString(),
            TimeSpan.FromSeconds(1),
            2,
            item =&amp;gt; Console.WriteLine(&amp;quot;Processed: &amp;quot; + item)
        )).ToArray();

// Create a producer based on an IEnumerable of strings from &amp;quot;Item-01&amp;quot; to &amp;quot;Item-20&amp;quot;.
var producer = new EnumeratorProducer&amp;lt;string&amp;gt;(Enumerable.Range(1, 20).Select(x =&amp;gt; &amp;quot;Item-&amp;quot; + x.ToString(&amp;quot;00&amp;quot;)));

// Create the MainProcess... all the internal logic for parallelization is here.
ProducerConsumersProcess&amp;lt;string&amp;gt; p = 
    new ProducerConsumersProcess&amp;lt;string&amp;gt;(
        producer,
        TimeSpan.FromMilliseconds(800),
        consumers,
        3);

// Start the process. This call blocks until the parallel process fails or ends.
p.Start();

Console.WriteLine(&amp;quot;Process finished!&amp;quot;);
&lt;/pre&gt;&lt;br /&gt;
Output is:&lt;br /&gt;
&lt;pre&gt;Processed: Item-01
Processed: Item-02
Processed: Item-03
Processed: Item-04
Processed: Item-05
Processed: Item-06
Processed: Item-08
Processed: Item-09
Processed: Item-07
Processed: Item-11
Processed: Item-12
Processed: Item-10
Processed: Item-14
Processed: Item-16
Processed: Item-17
Processed: Item-13
Processed: Item-15
Processed: Item-18
Processed: Item-19
Processed: Item-20
Process finished!&lt;/pre&gt;&lt;br /&gt;
If you run the code (TEAM.Commons.Threading.SampleConsole) you&#39;ll see how the execution pauses at some points. That&#39;s because the buffer gets emptied and the consumers are waiting for the producer to produce more items. In the real world you should adjust the parameters to avoid these pauses: buffer size, producer pause time when buffer is full, consumers pause time when buffer is empty.&lt;br /&gt;
&lt;br /&gt;
Next post will be about the details of TEAM.Commons.Threading.&lt;br /&gt;
&lt;br /&gt;
Remember, you can get all this code for free at bitbucket: &lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/overview&quot;&gt;http://bitbucket.org/rodolfograve/team.commons/overview&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Check it out to get ideas, or simply use it as it is. It&#39;s working out for me and my team.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/3199388266563352543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/3199388266563352543' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/3199388266563352543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/3199388266563352543'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2010/09/teamcommons-threading-part-1.html' title='TEAM.Commons: Threading - part 1'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-1475981618756351054</id><published>2010-09-18T08:24:00.004+01:00</published><updated>2010-10-19T21:48:58.292+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><title type='text'>TEAM.Commons: Formatting objects for human reading</title><content type='html'>This is the 3rd of several posts about TEAM.Common, a set of functionality I use in every project and that I&#39;d like to share. The index is here:&lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&quot;&gt;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Converting an arbitrary object into a human-readable string is something I need all the time, specially for logging.&lt;br /&gt;
&lt;br /&gt;
TEAM.Commons has the &lt;i&gt;PrettyFormat()&lt;/i&gt; extension method for the &lt;b&gt;object&lt;/b&gt; class that performs this task. For an instance of a class like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public class CyclicClass
{
    public int IntProperty { get; set; }
    public SimpleClass SimpleProperty { get; set; }
    public CyclicClass CyclicProperty { get; set; }
}
&lt;/pre&gt;&lt;br /&gt;
The output of &lt;b&gt;.PrettyFormat()&lt;/b&gt; would be:&lt;br /&gt;
&lt;pre&gt;CyclicClass {
IntProperty=&#39;7&#39;,
SimpleProperty=&#39;SimpleClass {
 StringProperty=&#39;My string&#39;,
 IntProperty=&#39;5&#39;,
 DateProperty=&#39;3/2/2010 12:00:00 AM&#39;,
}&#39;,
CyclicProperty=&#39;CyclicClass {
 nIntProperty=&#39;7&#39;,
 SimpleProperty=&#39;SimpleClass {
  -- EXCLUDED (Too deep) --
 }&#39;,
  CyclicProperty=&#39;CyclicClass {
   -- EXCLUDED (Too deep) --
  }&#39;,
 }&#39;,
}
&lt;/pre&gt;&lt;br /&gt;
As you can see, by default it will go &lt;i&gt;down&lt;/i&gt; only 1 level . Properties beyond that level will be rendered as &quot;-- EXCLUDED (Too deep) --&quot;. There is an overload to specify an arbitrary deepness: .PrettyFormat(10).&lt;br /&gt;
&lt;br /&gt;
The PrettyFormat method handles a lot of special cases: enum, IEnumerable, DateTimes, string, int, etc, providing an appropiate format for these types. You don&#39;t want to see an string as:&lt;br /&gt;
&lt;pre&gt;String {
 Length=14,
 Empty=...
}
&lt;/pre&gt;&lt;br /&gt;
but rather as:&lt;br /&gt;
&lt;pre&gt;The value of my string&lt;/pre&gt;&lt;br /&gt;
Thanks to the &quot;magic&quot; of extension methods, you can even call it on null references, saving a lot of &quot;if&quot; instructions:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;object o = null;
o.PrettyFormat();
&lt;/pre&gt;&lt;br /&gt;
The output of the former code is: &amp;lt;NULL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember, you can get all this code for free at bitbucket: &lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/overview&quot;&gt;http://bitbucket.org/rodolfograve/team.commons/overview&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Check it out to get ideas, or simply use it as it is. It&#39;s working out for me and my team.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/1475981618756351054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/1475981618756351054' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/1475981618756351054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/1475981618756351054'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2010/09/teamcommons-formatting-objects-for.html' title='TEAM.Commons: Formatting objects for human reading'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-6763899986798406201</id><published>2010-09-12T13:09:00.030+01:00</published><updated>2010-10-19T21:49:37.458+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CQRS"/><category scheme="http://www.blogger.com/atom/ns#" term="Queries"/><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><title type='text'>TEAM.Commons: Infrastructure for the Query part of CQRS (or just for querying)</title><content type='html'>This is the 2nd of several posts about TEAM.Common, a set of functionality I use in every project and that I&#39;d like to share. The index is here: &lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&quot;&gt;http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
It all started with some CQRS reading (Command and Query Responsibility Segregation).&lt;br /&gt;
&lt;br /&gt;
The idea of having a separated model only for querying seemed very valuable even outside a &quot;classic&quot; CQRS implementation, so we started applying it everywhere using an architecture like:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSOcD8QyhE6RaqNQJJcNRhfEZO1Oo0mQ00fO6efPk6wehBKQLV81lFEGpBBD570W_x6sOoYi9Ai1lOV-39Z_IUkpO1apbhtqaxf39KNLBV10KRegK40ZblvOPy0a_TkOnOIkQhhHtLNq0/s1600/DbConnectionExtensions-Use.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSOcD8QyhE6RaqNQJJcNRhfEZO1Oo0mQ00fO6efPk6wehBKQLV81lFEGpBBD570W_x6sOoYi9Ai1lOV-39Z_IUkpO1apbhtqaxf39KNLBV10KRegK40ZblvOPy0a_TkOnOIkQhhHtLNq0/s320/DbConnectionExtensions-Use.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
At this point, the implementation of the SqlSomeModelQueries was always something like this:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public IEnumerable&amp;lt;somemodel&amp;gt; GetAllWithCondition(string condition1, int condition2)
{
  using (var connection = new SqlConnection(ConnectionString))
  {
    var cmd = connection.CreateCommand(&quot;select A, B, C, ... from T1 inner join T2 ... where ...&quot;);
    using (var reader = cmd.ExecuteReader())
    {
      while (reader.Read())
      {
        SomeModel result = new SomeModel()
        {
          // Missing null checkings, safe conversions, etc
          A = Convert.ToInt32(reader[&quot;A&quot;].GetValue()), 
          B = Convert.ToString(reader[&quot;B&quot;].GetValue())
          // ... More properties
        };
        yield return result; // We don&#39;t want to keep all the items in memory.
      }
    }
  }
}
&lt;/pre&gt;&lt;br /&gt;
Obviously, after implementing this 3 times I decided I needed some infrastructure that will save us from repeating all this code over and over, with all the benefits that come with it.&lt;br /&gt;
&lt;br /&gt;
You can find the complete implementation in &lt;a href=&quot;https://bitbucket.org/rodolfograve/team.commons&quot;&gt;https://bitbucket.org/rodolfograve/team.commons&lt;/a&gt;. Check the MapperExtensions and DbConnectionExtensions classes. Using this infrastructure the code above is:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public IEnumerable&amp;lt;SomeModel&amp;gt; GetAllWithCondition(string condition1, int condition2)
{
  using (var connection = new SqlConnection(ConnectionString))
  {
    foreach (var item in connection.GetAllWithStreaming&amp;lt;SomeModel&amp;gt;(&quot;select A, B, C, ... from T1 inner join T2 ... where ...&quot;))
    // There is an overload to pass an SqlCommand in case you need to use an SqlCommand with parameters.
    {
      yield return item;
    }
  }
}
&lt;/pre&gt;&lt;br /&gt;
There are many details you must take into account if you want to do this by yourself:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Reflection is always very tricky to get right.&lt;/li&gt;
&lt;li&gt;Reflection is slow, so use something like &lt;a href=&quot;http://fasterflect.codeplex.com/&quot;&gt;Fasterflect&lt;/a&gt; and its cache features.&lt;/li&gt;
&lt;li&gt;There are a lot of special cases.&lt;/li&gt;
&lt;li&gt;You should add as much information as possible in the exception messages.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Remember, you can get all this code for free at bitbucket: &lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/overview&quot;&gt;http://bitbucket.org/rodolfograve/team.commons/overview&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Check it out to get ideas, or simply use it as it is. It&#39;s working out for me and my team.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/6763899986798406201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/6763899986798406201' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/6763899986798406201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/6763899986798406201'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2010/09/teamcommons-infrastructure-for-query.html' title='TEAM.Commons: Infrastructure for the Query part of CQRS (or just for querying)'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSOcD8QyhE6RaqNQJJcNRhfEZO1Oo0mQ00fO6efPk6wehBKQLV81lFEGpBBD570W_x6sOoYi9Ai1lOV-39Z_IUkpO1apbhtqaxf39KNLBV10KRegK40ZblvOPy0a_TkOnOIkQhhHtLNq0/s72-c/DbConnectionExtensions-Use.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-1443487268043271188</id><published>2010-09-12T12:53:00.010+01:00</published><updated>2010-10-19T21:46:12.623+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="TEAM.Commons"/><title type='text'>TEAM.Commons: Introduction</title><content type='html'>This is the 1st of several posts about TEAM.Common, a set of functionality I use in every project and that I&#39;d like to share.&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-infrastructure-for-query.html&quot;&gt;Querying.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-formatting-objects-for.html&quot;&gt;Formatting objects into readable strings.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-threading-part-1.html&quot;&gt;Threading - part 1 (introduction)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-threading-part-2.html&quot;&gt;Threading - part 2 (parallelization)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://rodolfograve.blogspot.com/2010/09/teamcommons-messaging-before-threading.html&quot;&gt;Messaging (in-process and inter-process)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
For some time I&#39;ve been trying to organize, stabilize and share some common code I use in all my projects and that I find myself copying over and over.&lt;br /&gt;
&lt;br /&gt;
This code matures with me and it will be nice to keep some part of my evolution as a developer in this code&#39;s history.&lt;br /&gt;
&lt;br /&gt;
Last time I published what I called &lt;a href=&quot;http://rodolfograve.blogspot.com/2009/07/romialyonet-sdk-is-public.html&quot;&gt;Romialyo SDK&lt;/a&gt;. Since then I have already made some improvements and stopped using git in favor of Mercurial, so here is the new &lt;a href=&quot;https://bitbucket.org/rodolfograve/team.commons&quot;&gt;TEAM.Commons&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I&#39;ll try to blog about it because I feel there are many things in there that could be used by many people and more importantly, I&#39;d love to get some feedback on this code because it contains what I feel are the best things I&#39;ve coded.&lt;br /&gt;
&lt;br /&gt;
Any improvement on this code will be a direct improvement on my abilities.&lt;br /&gt;
&lt;br /&gt;
Remember, you can get all this code for free at bitbucket: &lt;a href=&quot;http://bitbucket.org/rodolfograve/team.commons/overview&quot;&gt;http://bitbucket.org/rodolfograve/team.commons/overview&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Check it out to get ideas, or simply use it as it is. It&#39;s working out for me and my team.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/1443487268043271188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/1443487268043271188' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/1443487268043271188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/1443487268043271188'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2010/09/teamcommons-introduction.html' title='TEAM.Commons: Introduction'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-14355611506421614</id><published>2010-07-17T09:09:00.001+01:00</published><updated>2010-10-19T21:51:13.308+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="My Applications"/><title type='text'>Another award for TEAM&#39;s TimeTracker</title><content type='html'>This has happened many times in the last few months, but every time is important:&lt;br /&gt;
&lt;br /&gt;
TEAM&#39;s TimeTracker has been awarded the &quot;Famous Software Award&quot; by &quot;Download.FamousWhy.com&quot;:&lt;br /&gt;
&lt;a href=&quot;http://download.famouswhy.com/team__039_s_timetracker/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://download.famouswhy.com/awards/Famous_Software_Award_Logo.png&quot;
alt=&quot;TEAM&amp;#039;s TimeTracker&quot; style=&quot;border:0&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
These later awards have inspired me to spend some time on my old applications trying to make them better, and I have recently released &lt;a href=&quot;https://sourceforge.net/projects/wpf-timetracker/&quot;&gt;version 2.4.0 of TEAM&#39;s TimeTracker&lt;/a&gt; and &lt;a href=&quot;https://sourceforge.net/projects/db4ostudio/&quot;&gt;version 0.2.0 of TEAM&#39;s Db4o Management Studio&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I&#39;d like to ask everyone who is using or have used these application to leave their comments and suggestions at bitbucket.org:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.timetracker/issues/new&quot;&gt;TEAM&#39;s TimeTracker: http://bitbucket.org/rodolfograve/team.timetracker/issues/new&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bitbucket.org/rodolfograve/team.db4omanagementstudio/issues?status=new&quot;&gt;TEAM&#39;s Db4o Management Studio: http://bitbucket.org/rodolfograve/team.db4omanagementstudio/issues?status=new&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/14355611506421614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/14355611506421614' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/14355611506421614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/14355611506421614'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2010/07/another-award-for-teams-timetracker.html' title='Another award for TEAM&#39;s TimeTracker'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-526404163031670572</id><published>2010-06-29T09:16:00.004+01:00</published><updated>2010-06-29T11:18:51.155+01:00</updated><title type='text'>I&#39;m a db4o MVP</title><content type='html'>&lt;img src=&quot;https://developer.db4o.com/Portals/0/images/dVP-Badge-2010.gif&quot; alt=&quot;db4oMVP2010&quot;/&gt;&lt;br /&gt;
&lt;br /&gt;
Well, this came as a great surprise to me. Today I received an email from &lt;a href=&quot;http://db4o.com&quot;&gt;db4o.com&lt;/a&gt; explaining I had been selected as db4o MVP thanks to my &lt;a href=&quot;http://sourceforge.net/projects/db4ostudio/&quot;&gt;TEAM&#39;s db4o Management Studio&lt;/a&gt; application. (Blog post &lt;a href=&quot;http://rodolfograve.blogspot.com/2009/09/teams-db4o-management-studio-v010-is.html&quot;&gt;here&lt;/a&gt;. Download from &lt;a href=&quot;http://sourceforge.net/projects/db4ostudio/&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I&#39;m the 11th in the list of MVPs: &lt;a href=&quot;https://developer.db4o.com/Resources/ProfessionalCommunity/Db4oMostValuedProfessional/dVPDirectory2010.aspx&quot;&gt;dVPDirectory2010&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I&#39;ve been using db4o for a while. About a year ago I created the db4o Management Studio because I found no suitable tool to inspect a db4o database. This is an issue when you don&#39;t have the definition of the classes you have stored in that database, or even when you just don&#39;t want to spend time writing an application to inspect the database.&lt;br /&gt;
&lt;br /&gt;
Finally, here is an extract from the email:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;Let me be the first to congratulate you! You have been selected as a db4o Most Valued Professional (dVP) awardee for the year 2010.&lt;br /&gt;
The dVP is our community program first launched at the db4o User Conference (dUC) in July 2006 in London. The purpose of the initiative is to honor individuals like yourself who have shown a large commitment towards the db4o Community - by providing valuable peer support in the forums or outstanding contributions to the db4o software ecosystem (such as db4o related projects, articles, books, translations, etc) or by consistently spreading the word about the db4o technology (through blogs, webcasts, etc). The status is awarded for a given year (in this case 2010) and has to be re-earned every year.&lt;/blockquote&gt;&lt;br /&gt;
Nice :-)</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/526404163031670572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/526404163031670572' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/526404163031670572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/526404163031670572'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2010/06/im-db4o-mvp.html' title='I&#39;m a db4o MVP'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-2431359375108591125</id><published>2010-06-11T23:00:00.091+01:00</published><updated>2010-10-19T21:51:37.825+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Patterns"/><title type='text'>Handling configuration in Enterprise environments</title><content type='html'>Have you ever faced the problem of handling a complicated configuration in an Enterprise environment where there are dozens of components interacting (databases, web services, FTP sites, queues, etc)?&lt;br /&gt;
&lt;br /&gt;
Mix this with automated deployment and some deployment environments (integration, QA, staging, production) and you have a complex problem to solve. A wrong solution could undermine your whole architecture, making deployment chaotic and untestable.&lt;br /&gt;
&lt;br /&gt;
We&#39;ve faced this situation and we&#39;ve come up with what I believe is a nice solution. Let&#39;s state our requirements, which is always a good exercise when solving a problem:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R1- Automatic deployment&lt;/b&gt;&lt;br /&gt;
We need our solution not to interfere with automatic deployment.&lt;br /&gt;
&lt;br /&gt;
To me, this means to keep code and configuration separated. I don&#39;t want a super-complex deployment script which must handle deployment in every environment. I also don&#39;t want to include all my environment&#39;s passwords in this deployment script.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R2- Ease of use and maintenance for system administrators&lt;/b&gt;&lt;br /&gt;
Our solution must be easy to use and maintain for system administrators.&amp;nbsp;It must be very easy for administrators to create and maintain configuration for each environment and to track changes done to the configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R3- Robustness&lt;/b&gt;&lt;br /&gt;
I want all the applications to share the same configuration, specially in our environment, where several applications interact with the same databases/web services/etc. It must be impossible for application A to point to a database &lt;i&gt;Db_staging&lt;/i&gt; while application B points to &lt;i&gt;Db_integration&lt;/i&gt;. They must always point to the same database.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R4- Flexibility&lt;/b&gt;&lt;br /&gt;
At least in our case, the staging/QA/integration environments are far from being identical to our production environment, mainly due to infrastructure expenses: we have 10+ servers in production and we only have 2 servers per environment. We can not afford to have 10+ servers per environment.&lt;br /&gt;
&lt;br /&gt;
Besides, you never know what a developer will need in order to test the application in their boxes.&lt;br /&gt;
&lt;br /&gt;
So, our solution must allow a great deal of flexibility, assuming nothing about the different environments.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R5- Ease of use for developers&lt;/b&gt;&lt;br /&gt;
&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;It must be very easy for developers to get the configuration values and to tamper with them in their development environments.&lt;/div&gt;&lt;br /&gt;
&lt;b&gt;R6- Security&lt;/b&gt;&lt;br /&gt;
Finally, for us, it was very important to have one single database user per application. But this could be a very particular requirement.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The (simplified) solution&lt;/b&gt;&lt;br /&gt;
S1- Global configuration file: create a file (or files) that contain all your configuration resources (connection strings to databases, ftp connection details, urls to web services, etc).&lt;br /&gt;
&lt;br /&gt;
We choose an XML file with key/values:&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&amp;lt;add name=&quot;MyDB1&quot; value=&quot;Data Source=stagingSQL;Initial Catalog=MyDB;User ID=user;Password=pass&quot;/&amp;gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
S2- Create a copy of this file per environment, and put it under version control so that you can check for modifications.&lt;br /&gt;
&lt;br /&gt;
S3- Create a project in your CI server that deploys this configuration file(s) to the right servers when a change is detected.&lt;br /&gt;
&lt;br /&gt;
So far we have handled requirements:&lt;br /&gt;
&lt;b&gt;R1-&lt;/b&gt; We have automatic deployment of the configuration because it is a simple plain-text file under version control that is automatically deployed by our CI server (or any other mechanism you prefer).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R2-&lt;/b&gt; System administrators only have to commit changes to the configuration files in the right branch in order to modify an envinroment&#39;s configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R3-&lt;/b&gt; There isn&#39;t a configuration file per application but a single &quot;source of truth&quot;: the global.config file. There is no way you can get two different values for the same key.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R4-&lt;/b&gt; There are no limits to what you can place in a text file. The only requirement is that the keys are the same for all the files, otherwise the applications won&#39;t find the resources they are asking for. That should be flexible enough and some naming conventions can make it simple.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R5-&lt;/b&gt; Build an API to access the configuration values. Make it very transparent to users. Our client calls look like this: &lt;i&gt;Environment.Current.GetDbConnectionString(&quot;MyKey&quot;)&lt;/i&gt;, which is very similar to AppSettings.ConnectionStrings[&quot;MyKey&quot;].&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;R6-&lt;/b&gt; Using a very simple template for the values you can make your API to automatically handle this kind of security:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Have a users.config file where you have ApplicationIds -&amp;gt; User/Password.&lt;/li&gt;

&lt;li&gt;Make your API&amp;nbsp;request the running application to provide its ApplicationId before the application can access any configuration values: &lt;i&gt;Environment.Initialize(&quot;MyAppId&quot;); &lt;/i&gt;Any call to Environment.Current should fail if no ApplicationId has been provided.&lt;/li&gt;

&lt;li&gt;Make your connection strings look like this:&lt;br /&gt;
&lt;i&gt;&amp;lt;add name=&quot;MyDB1&quot; value=&quot;Data Source=stagingSQL;Initial Catalog=MyDB;User ID={user};Password={password}&quot;/&amp;gt;&lt;/i&gt;&lt;/li&gt;

&lt;li&gt;Finally, make your&amp;nbsp;&lt;i&gt;GetDbConnectionString &lt;/i&gt;load the ConnectionString, the ApplicationId -&amp;gt; User/Password values, and replace the placeholders with the actual values.&lt;/li&gt;
&lt;/ul&gt;We have found this approach to be a very nice solution. Hope it helps you find your own, or you can use this one as it is.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/2431359375108591125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/2431359375108591125' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/2431359375108591125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/2431359375108591125'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2010/06/handling-configuration-in-enterprise.html' title='Handling configuration in Enterprise environments'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-2826692914553623514</id><published>2009-09-25T13:49:00.010+01:00</published><updated>2010-10-19T21:50:10.717+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Patterns"/><title type='text'>My best WPF magic for Model-View-ViewModel (M-V-VM) with Routed Commands</title><content type='html'>Some time ago I had the required free time to think about a nice way to implement a set of classes and ideas that will allow me to build a WPF application that: &lt;br /&gt;
&lt;br /&gt;
- Honors the Model-View-ViewModel pattern.&lt;br /&gt;
- Keeps the view as simple as possible, ideally as a template and no code-behind.&lt;br /&gt;
- Uses the power of the Command pattern in WPF (Routed Commands), keeping the View agnostic about the logic encapsulated in commands.&lt;br /&gt;
&lt;br /&gt;
After some attempts, the result are 2 classes that make this all possible in a very elegant way, I think. The first class is the ViewModelBase (fragment):&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
public abstract class ViewModelBase&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;// Something like the &quot;Null object pattern&quot;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;protected static ViewModelBase EmptyViewModel = new EmptyViewModel();&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;public IEnumerable&lt;commandbinding&gt; CommandBindings { get; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;public IEnumerable&lt;inputbinding&gt; InputBindings { get; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;protected abstract void PrepareBindings();&lt;br /&gt;
}&lt;br /&gt;
&lt;/inputbinding&gt;&lt;/commandbinding&gt;&lt;/code&gt;&lt;br /&gt;
The ViewModelBase class, as its name implies, is supposed to be the base class of all the ViewModels, and it is here where you define what to do when a RoutedCommand is executed. It is the glue between the RoutedCommands in the View and the command execution logic in the ViewModel.&lt;br /&gt;
&lt;br /&gt;
Then, there is the ViewModelControl class (full text):&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
public class ViewModelControl : ContentControl&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;protected override void OnContentChanged(object oldContent, object newContent)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;{&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;CommandBindings.Clear();&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;ViewModelBase viewModel = newContent as ViewModelBase;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;if (viewModel != null)&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;foreach (var binding in viewModel.CommandBindings)&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;CommandBindings.Add(binding);&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;InputBindings.Clear();&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;foreach (var binding in viewModel.InputBindings)&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;InputBindings.Add(binding);&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;base.OnContentChanged(oldContent, newContent);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;}&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
This control takes care of associating the CommandBindings to the visual elements so that the RoutedCommands mechanism works.&lt;br /&gt;
&lt;br /&gt;
And that&#39;s it. There are some implementation details missing, but with these classes in place you just have to:&lt;br /&gt;
&lt;br /&gt;
1- Create your ViewModel classes inheriting from ViewModelBase.&lt;br /&gt;
2- Provide the implementation of their PrepareBindings methods.&lt;br /&gt;
3- Create the templates for your ViewModels.&lt;br /&gt;
4- Bind your controls to the commands.&lt;br /&gt;
&lt;br /&gt;
Using this implementation you&#39;ll get these results:&lt;br /&gt;
&lt;br /&gt;
1- You&#39;ll have your RoutedCommands.&lt;br /&gt;
2- Logic for these commands will be in your ViewModel classes, where you can test it.&lt;br /&gt;
3- No event handlers, no code-behinds required.&lt;br /&gt;
&lt;br /&gt;
Mix this with INotifyPropertyChanged in your ViewModels and DataModels and you&#39;ll have a cool architecture for your View. Here&#39;s an example:&lt;br /&gt;
&lt;br /&gt;
1. Define a routed commands:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
public class ViewCommands&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;public static RoutedCommand MyRoutedCommand;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;static ViewCommands()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;{&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;MyRoutedCommand = new RoutedCommand(&quot;MyRouted&quot;, typeof(ViewCommands));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;}&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
2. Define a ViewModel:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
public class MyViewModel : ViewModelBase&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;protected override void PrepareBindings()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;{&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;this.AddCommandBindings(new CommandBinding(&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;ViewCommands. MyRoutedCommand,&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;(x, y) =&amp;gt; DoSomethingIfMyRoutedIsExecutedOnThisViewModel(),&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;(x, y) =&amp;gt; y.CanExecute = CanMyRoutedCommandBeExecuted));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;}&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
3. Finally define a view with a ViewModelControl and some templates for your ViewModels and DataModels:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&amp;lt;Window&lt;br /&gt;
xmlns:baseViews=&quot;clr-namespace:Namespace.Of.ViewModelControl&quot;&lt;br /&gt;
xmlns:models=&quot;clr-namespace:Namespace.Of.ViewModels&quot;&lt;br /&gt;
...&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;Window.Resources&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;DataTemplate DataType=&quot;{x:Type models:MyViewModel}&quot;&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;Button Content=&quot;Execute MyRoutedCommand&quot; Command=&quot;model:ViewCommands.MyRoutedCommand&quot; /&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/DataTemplate&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/Window.Resources&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;Grid&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;baseViews:ViewModelControl Content=&quot;{Binding}&quot; /&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/Grid&amp;gt;&lt;br /&gt;
&amp;lt;/Window&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
That&#39;s it. It works very nicely, try it.&lt;br /&gt;
&lt;br /&gt;
I think I&#39;ll be posting a more complete article about this soon. In the mean time:&lt;br /&gt;
&lt;br /&gt;
- What do you think?&lt;br /&gt;
- Want to see some real code?</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/2826692914553623514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/2826692914553623514' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/2826692914553623514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/2826692914553623514'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2009/09/my-best-wpf-magic-for-model-view.html' title='My best WPF magic for Model-View-ViewModel (M-V-VM) with Routed Commands'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-8269509932100674156</id><published>2009-09-21T20:43:00.002+01:00</published><updated>2010-10-19T21:51:13.309+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="My Applications"/><title type='text'>TEAM&#39;s Db4o Management Studio v0.1.0 is out</title><content type='html'>Many times in the latest couple of months I&#39;ve found my self hoping for a tool that would allow me to inspect a db4o database without using the classes that were used to save the data.&lt;br /&gt;
&lt;br /&gt;
One of these situations is when I&#39;m migrating an old classes&#39; schema into a new one, and I really need to see what&#39;s inside the database to implement the migration.&lt;br /&gt;
&lt;br /&gt;
After so much hoping and dissapointment on the Db4o Object Manager, I decided to implement a simple tool to do the job. The result is a very simple (and crude) application.&lt;br /&gt;
&lt;br /&gt;
Don&#39;t expect anything fancy, but please, send any comments and suggestions, and feel free to copy the idea and make a better tool. The db4o community will thank you.&lt;br /&gt;
&lt;br /&gt;
You can get the application from sourceforge &lt;a href=&quot;http://sourceforge.net/projects/db4ostudio/&quot;&gt;here&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/8269509932100674156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/8269509932100674156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/8269509932100674156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/8269509932100674156'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2009/09/teams-db4o-management-studio-v010-is.html' title='TEAM&#39;s Db4o Management Studio v0.1.0 is out'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-2559119547871829387</id><published>2009-08-27T16:08:00.004+01:00</published><updated>2010-10-19T21:51:13.309+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="My Applications"/><title type='text'>TEAM&#39;s TimeTracker v2.2.0 is out</title><content type='html'>A long time ago I built an application to manage the time me and my co-workers spent at work. I built the tool to be very simplistic and useful.&lt;br /&gt;&lt;br /&gt;Although I published it in SourceForge since the beginning, I didn&#39;t have notice of any other users of the application until recently, on July 15th 2009, when Softpedia included the application in their database:&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.softpedia.com/get/Scheduling/TEAM-s-TimeTracker.shtml&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.softpedia.com/images/softpedia_download_small.gif&quot;/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From that moment on some people started using it and it became obvious that the errors which we were already used to were a blocking issue for most people out there. That&#39;s why I&#39;ve spent some time fixing those errors (and hopefully not introducing new ones).&lt;br /&gt;&lt;br /&gt;Thanks to Randy Schultz for reporting most of the issues, and thanks to my former co-workers in Expectra for using the application no matter what, the TEAM&#39;s TimeTracker v2.2.0 is available at SourceForge:&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://sourceforge.net/projects/wpf-timetracker/&quot;&gt;http://sourceforge.net/projects/wpf-timetracker/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This version is able to automatically migrate the old data you had if you were using v0.1.0.&lt;br /&gt;&lt;br /&gt;I hope you like it.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/2559119547871829387/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/2559119547871829387' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/2559119547871829387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/2559119547871829387'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2009/08/teams-timetracker-v220-is-out.html' title='TEAM&#39;s TimeTracker v2.2.0 is out'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-402779665604076928</id><published>2009-07-26T14:45:00.009+01:00</published><updated>2009-08-27T16:07:57.340+01:00</updated><title type='text'>Romialyo.NET SDK is public (with an ESB)</title><content type='html'>I&#39;ve decided to publish the libraries I use for development in most of my projects. You can get it &lt;a href=&quot;http://rodolfograve.github.com/Romialyo.NET-SDK&quot;&gt;here, at github&lt;/a&gt;. It currently contains:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Several extensions to the .NET Framework I found myself re-coding many times.&lt;/li&gt;&lt;li&gt;An Enterprise Service Bus implementation, inspired in the good concepts from &lt;a href=&quot;nservicebus.com&quot;&gt;nServiceBus&lt;/a&gt; and RhinoESB.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Romialyo&#39;s ESB supports MSMQ and in-process message sending.&lt;br /&gt;&lt;br /&gt;This ESB has become central to most of my projects so it was very important for me to have this code in a unique location and manage its versions properly.&lt;br /&gt;&lt;br /&gt;Romialyo&#39;s ESB was started from the ground, trying to improve on nServiceBus code which I found hard to compile, extend and understand. The biggest stopper I found with nServiceBus was that it was too difficult for me to create an InProcess transport that will allow me to use the ESB as an &lt;a href=&quot;http://martinfowler.com/eaaDev/EventAggregator.html&quot;&gt;Event Aggregator&lt;/a&gt; to communicate views in Smart Client applications.&lt;br /&gt;&lt;br /&gt;In &lt;a href=&quot;http://feedproxy.google.com/~r/CodeBetter/~3/Ueb7pbqdl08/braindump-on-the-event-aggregator-pattern.aspx&quot;&gt;this&lt;/a&gt; blog post, Jeremy D. Miller exposes his conclusion about the &quot;Event Aggregator = Service Bus&quot; idea (braindump #12). I&#39;ve been using a service bus with an events based in-process transport as the Event Aggregator in my applications for a while, and I must say I&#39;ve found the idea very attractive.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/402779665604076928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/402779665604076928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/402779665604076928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/402779665604076928'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2009/07/romialyonet-sdk-is-public.html' title='Romialyo.NET SDK is public (with an ESB)'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-50548299979181668.post-8268605217016068748</id><published>2009-07-15T09:57:00.003+01:00</published><updated>2010-10-19T21:51:13.310+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="My Applications"/><title type='text'>TEAM&#39;s TimeTracker es realmente público ahora</title><content type='html'>Hoy he recibido una sorpresa: TEAM&#39;s TimeTracker pasa a formar parte de la base de software de Softpedia.&lt;br /&gt;&lt;br /&gt;Siempre pensé que la aplicación era útil, sin duda lo ha sido para mi y para los Expectros que la utilizan a diario, pero tampoco hay dudas de que tiene demasiados errores. &lt;br /&gt;&lt;br /&gt;Creo que esta noticia hará que le dedique un tiempo a pulirla un poco.</content><link rel='replies' type='application/atom+xml' href='http://rodolfograve.blogspot.com/feeds/8268605217016068748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/50548299979181668/8268605217016068748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/8268605217016068748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/50548299979181668/posts/default/8268605217016068748'/><link rel='alternate' type='text/html' href='http://rodolfograve.blogspot.com/2009/07/teams-timetracker-es-realmente-publico.html' title='TEAM&#39;s TimeTracker es realmente público ahora'/><author><name>RG</name><uri>http://www.blogger.com/profile/09921737191231131272</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>