Billy McCafferty : ASP.NEThttp://devlicio.us/blogs/billy_mccafferty/archive/tags/ASP.NET/default.aspxTags: ASP.NETenCommunityServer 2008.5 SP1 (Build: 31106.3070)The dojo is open... www.ITSamuraiSchool.comhttp://devlicio.us/blogs/billy_mccafferty/archive/2009/05/18/the-dojo-is-open-www-itsamuraischool-com.aspxTue, 19 May 2009 01:52:00 GMT40756a8b-6212-4073-9d98-6c26781577de:46899Billy McCafferty11<p>Codai&#39;s IT Samurai School is open for enrollment.&nbsp; It&#39;s Flash, so it&#39;ll take a few moments to download...but I hope you&#39;ll agree it&#39;s worth the wait...&nbsp; <a href="http://www.itsamuraischool.com">http://www.itsamuraischool.com</a></p>
<p>A few fun facts about the website and the school itself:</p>
<ul>
<li>Born our of a short conversation at a BBQ concerning my desire to do high quality training</li>
<li>100% Flash front-end, outside of the checkout screens</li>
<li>Built on latest <a href="http://code.google.com/p/sharp-architecture/">S#arp Architecture</a> available from the trunk
</li>
<li>6 months in the making, including the site and class preparation</li>
<li>21 classes initially, including ASP.NET MVC, Object-Oriented JavaScript, SQL Server Integration Services, S#arp Architecture and many others</li>
<li>5 cities initially, including Denver, Austin, San Jose, Washington DC, and Seattle</li>
<li>A handful of top notch trainers, including myself (IMHO)</li>
<li>Guest speakers and occasional, one-run only, unique courses</li>
</ul>
<p><a title="IT Samurai School" href="http://www.itsamuraischool.com"><img alt="Codai&#39;s IT Samurai School" style="border:0;" src="http://devlicio.us/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/billy_5F00_mccafferty/dojo_5F00_screenshot.png" border="0" /></a></p>
<p>We look forward to seeing you in class!</p>
<p>Billy McCafferty</p><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=46899" width="1" height="1">Architecture.NETSoftware DevelopmentQuality AssuranceASP.NETSQL ServerProject ManagementPatternsTest-Driven DevelopmentAgile DevelopmentMVC.NETS#arp ArchitectureTips &amp; TricksDDDIntegrating Castle MonoRail into Legacy Codehttp://devlicio.us/blogs/billy_mccafferty/archive/2007/06/26/integrating-castle-monorail-into-legacy-code.aspxWed, 27 Jun 2007 01:18:00 GMT40756a8b-6212-4073-9d98-6c26781577de:30481Billy McCafferty13<p>After <a href="http://devlicious.com/blogs/billy_mccafferty/archive/2007/05/29/concise-introduction-to-castle-monorail.aspx">deciding to migrate</a> our current project to <a href="http://www.castleproject.org/monorail/index.html">Castle Project&#39;s&nbsp;MonoRail</a>, next came the task of going through the available documentation, forums and sample code to determine how best to integrate the MonoRail Project into our legacy application.&nbsp; What follows should serve as a solid tutorial if you choose to take this path with legacy code as well.&nbsp; (If you&#39;re beginning a new, ground-up solution, <a href="http://www.castleproject.org/monorail/gettingstarted/index.html">a&nbsp;getting starting sample</a> may be downloaded from the Castle Project website.)&nbsp; These integration steps make the following assumptions:</p>
<ul>
<li>Using Castle MonoRail Build 429 from the <a href="http://builds.castleproject.org/cruise/index.castle">Castle Build Server</a>; more recent builds should most likely work just as well.</li>
<li><a href="http://wiki.castleproject.org/index.php/MonoRail:Brail">Brail</a> has been selected as your view engine.</li>
<li>Your domain/core classes are kept in a separate assembly from the web project.</li>
<li>IIS is your web server of choice.</li>
</ul>
<p><strong>Integrating Castle MonoRail w/Brail Views into Legacy Code</strong></p>
<ol>
<li>From the build zip, add the following DLLs to your &quot;Solution Items&quot; folder:
<ul>
<li>Boo.Lang.dll</li>
<li>Boo.Lang.Compiler.dll</li>
<li>Boo.Lang.Parser.dll</li>
<li>Castle.Components.Common.EmailSender.dll</li>
<li>Castle.Components.Validator.dll</li>
<li>Castle.Core.dll</li>
<li>Castle.MonoRail.Framework.dll</li>
<li>Castle.MonoRail.View.Brail.dll</li>
</ul>
</li>
<li>Add a new project to your solution to hold the <a href="http://en.wikipedia.org/wiki/Model-view-controller">MVC</a> controllers.&nbsp; In my own applications, I name each assembly using the following convention:&nbsp; &lt;project name&gt;.&lt;assembly scope&gt;; e.g. MyProject.Controllers.&nbsp; (I discuss my default architecture in a <a href="http://devlicious.com/blogs/billy_mccafferty/archive/2006/10/05/_2800_My_2900_-Default-ASP.NET-Architecture.aspx">previous post</a>.)&nbsp; If you&#39;re already using <a href="http://www.codeproject.com/useritems/ModelViewPresenter.asp">MVP</a> or another separation-of-concerns technique which has a dedicated assembly for presentation logic, I still recommend adding a new controllers specific assembly.&nbsp; This should minimize confusion between what&#39;s using the &quot;old way&quot; and what&#39;s using the &quot;new way.&quot;</li>
<li>Within the controllers assembly, add references to:
<ul>
<li>Castle.Components.Common.EmailSender.dll</li>
<li>Castle.MonoRail.Framework.dll</li>
</ul>
</li>
<li>Within your web project, add references to:
<ul>
<li>The MyProject.Controllers project</li>
<li>Boo.Lang.dll</li>
<li>Boo.Lang.Compiler.dll</li>
<li>Boo.Lang.Parser.dll</li>
<li>Castle.Components.Validator.dll</li>
<li>Castle.Core.dll</li>
<li>Castle.MonoRail.View.Brail.dll</li>
</ul>
</li>
<li>Follow the <a href="http://wiki.castleproject.org/index.php/MonoRail:Getting_Started#First_Controller">First Controller steps in the Getting Started guide</a> to create your first controller, HomeController, in the controllers project.</li>
<li>Augment&nbsp;web.config with the following:
<p>&lt;configSections&gt;
&lt;section name=&quot;monoRail&quot;
type=&quot;Castle.MonoRail.Framework.Configuration.MonoRailSectionHandler, Castle.MonoRail.Framework&quot;&gt;
&lt;!-- Declared so that MonoRail views can be set
to communicate with domain layer classes --&gt;
&lt;section name=&quot;Brail&quot;
type=&quot;Castle.MonoRail.Views.Brail.BrailConfigurationSection, Castle.MonoRail.Views.Brail&quot;&gt;
&lt;/configSections&gt;
&lt;monoRail&gt;
&lt;controllers&gt;
&lt;assembly&gt;MyProject.Controllers&lt;/assembly&gt;
&lt;/controllers&gt;
&lt;viewEngine viewPathRoot=&quot;Views&quot; customEngine=&quot;Castle.MonoRail.Views.Brail.BooViewEngine, Castle.MonoRail.Views.Brail&quot;&gt;
&lt;/monoRail&gt;
&lt;Brail saveDirectory=&quot;Brail_Generated_Code&quot;
commonScriptsDirectory=&quot;CommonScripts&quot;&gt;
&lt;reference assembly=&quot;MyProject.Core&quot;/&gt;
&lt;/Brail&gt;
&lt;httpHandlers&gt;
&lt;!-- Have Castle MonoRail handle
anything with a rails extension --&gt;
&lt;add verb=&quot;*&quot; path=&quot;*.rails&quot;
type=&quot;Castle.MonoRail.Framework.MonoRailHttpHandlerFactory, Castle.MonoRail.Framework&quot;&gt;&lt;/add&gt;
&lt;!-- Block user access to Brail templates --&gt;
&lt;add verb=&quot;*&quot; path=&quot;*.brail&quot; type=&quot;System.Web.HttpForbiddenHandler&quot;&gt;&lt;/add&gt;
&lt;/httpHandlers&gt;
&lt;httpModules&gt;
&lt;add name=&quot;monorail&quot; type=&quot;Castle.MonoRail.Framework.EngineContextModule, Castle.MonoRail.Framework&quot;&gt;&lt;/add&gt;
&lt;/httpModules&gt;</p>
Note that &quot;MyProject.Core&quot; should be replaced with the assembly name which holds your domain/core classes. (There may be multiple.)&nbsp; Also, the documentation states that *.boo should be wired up with the HttpForbiddenHandler.&nbsp; Although the documentation has not been updated, the most recent code trunk requires that you mask the *.brail extension instead; but&nbsp;after doing this,&nbsp;the wiring doesn&#39;t seem to work for me in preventing a user from viewing the raw view.&nbsp; I&#39;m assuming I&#39;ve missed something here but wanted to show how it&#39;s supposed to work.</li>
<li>Adapt IIS to&nbsp;handle the&nbsp;rails extension as&nbsp;<a href="http://wiki.castleproject.org/index.php/MonoRail:Getting_Started#IIS_.28Internet_Information_Services.29">outlined in the&nbsp;Getting Started guide</a>&nbsp;for&nbsp;your&nbsp;website or&nbsp;virtual directory.</li>
<li>Build&nbsp;the controllers project&nbsp;and browse to <a href="http://localhost/MyProject/home/index.rails">http://localhost/MyProject/home/index.rails</a>.&nbsp; You should get an error as follows:&nbsp; &quot;Could not find view template: home\index&quot;</li>
<li>Add the following folder structure to&nbsp;the root of the web project: &nbsp;/Views/Home.</li>
<li>Add Index.brail and About.brail files to the Home directory and put differing &quot;hello world&quot; content in each (so you can tell them apart).&nbsp; You should now be able to browse to <a href="http://localhost/MyProject/home/index.rails">http://localhost/MyProject/home/index.rails</a> and <a href="http://localhost/MyProject/home/about.rails">http://localhost/MyProject/home/about.rails</a>&nbsp;while not breaking any of the existing functionality.</li>
</ol>
<p>The above steps represent the minimal&nbsp;actions necessary&nbsp;to get MonoRail integrated into a legacy application.&nbsp; Further options and capabilities may require further integration steps with additional Castle assemblies.&nbsp; Only integrate MonoRail into a legacy application after careful consideration of the maintenance implications.&nbsp; Developers will now need to be aware of multiple presentation models being maintained within the legacy application and how to deal with both.&nbsp; Introducing a paradigm shift into an existing application can cause a lot of havoc&nbsp;breaking the <a href="http://assets.cambridge.org/97805216/71590/excerpt/9780521671590_excerpt.pdf">adhere to the style of the original</a> rule of thumb.&nbsp; But sometimes, a style needs to be broken. ;)</p>
<p>Billy McCafferty</p>
<p><a href="http://www.dotnetkicks.com/kick/?url=http://devlicio.us/blogs/billy_mccafferty/archive/2007/06/26/integrating-castle-monorail-into-legacy-code.aspx"><img border="0" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://devlicio.us/blogs/billy_mccafferty/archive/2007/06/26/integrating-castle-monorail-into-legacy-code.aspx" alt="kick it on DotNetKicks.com" /> </a></p><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=30481" width="1" height="1">ASP.NETRefactoringCastle ProjectConcise Introduction to Castle MonoRailhttp://devlicio.us/blogs/billy_mccafferty/archive/2007/05/29/concise-introduction-to-castle-monorail.aspxTue, 29 May 2007 20:10:00 GMT40756a8b-6212-4073-9d98-6c26781577de:26810Billy McCafferty13<p>Henrik Feldt, a competitor in my latest coding challenge, sent me a <a href="http://www.ayende.com/hibernating-rhinos.aspx">link to an&nbsp;AVI presentation</a> given by <a href="http://www.ayende.com">Ayende</a> discussing <a href="http://www.castleproject.org/monorail/index.html">Castle MonoRail</a>, how it compares to Web Forms development, and the creation of a ground-up application based on this framework.&nbsp; The presentation is a little over an hour long and should greatly shorten the time needed for you to figure out what MonoRail&#39;s all about.&nbsp; In the presentation, Ayende does a great job of showing the strengths of MonoRail while not shying away from detailing the up-front work necessary to put it in place.</p>
<p>After using <a href="http://www.codeproject.com/useritems/ModelViewPresenter.asp">Model View Presenter</a> for 1 1/2 years, and after carefully reviewing <a href="http://mavnet.sourceforge.net/">other</a>&nbsp;<a href="http://blogs.meetandplay.com/WPierce/archive/2006/12/24/Revisited_MVP_Framework.aspx">separation-of-concern</a> <a href="http://www.codeplex.com/websf">alternatives</a>,&nbsp;my development team has&nbsp;decided to begin migrating towards Castle MonoRail.&nbsp; With MonoRail, we&#39;re hoping to have the fewest number of classes and lowest level of complexity while still supporting test driven development.&nbsp; My biggest concern with moving towards MonoRail was having to abandon third party user controls such as <a href="http://www.telerik.com/">telerik</a>.&nbsp; Although immensely valuable for speeding up development during the early stages of development, I&#39;m finding these types of controls very difficult&nbsp;to&nbsp;alter behaviors later on in a project&#39;s life cycle.&nbsp; Another concern, to some, is that MonoRail abandons the ASP.NET page life-cycle.&nbsp; After working within the added complexities of the ASP.NET page life-cycle for&nbsp;seven years, I&#39;m quite excited about getting back to a simpler web model.&nbsp; We&#39;ll see how this goes...</p>
<p>Anyway, be sure to check out <a href="http://www.ayende.com/hibernating-rhinos.aspx">Ayende&#39;s presentation</a> to help make up your own mind.</p>
<p>Billy McCafferty</p><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=26810" width="1" height="1">ASP.NETCastle ProjectIntegrate It! Coding Contest using Castle Projecthttp://devlicio.us/blogs/billy_mccafferty/archive/2007/05/02/integrate-it-coding-contest-w-castle-project.aspxThu, 03 May 2007 02:08:00 GMT40756a8b-6212-4073-9d98-6c26781577de:24285Billy McCafferty9<P>[Updated May 9, 2007: Clarified contest&nbsp;rules to&nbsp;downgrade some "requirements" to be "suggestions" instead.&nbsp; I.e., there's now a little more wiggle room in the implementation details.]</P>
<P>A contest guaranteed to challenge you!&nbsp; This contest involves integrating Castle Project facilities into an existing project that's pre-wired for <A class="" href="http://www.castleproject.org/container/index.html">Castle Project Windsor</A>.&nbsp; Have you wanted to try out some aspect oriented programming?&nbsp; This just&nbsp;<EM>may</EM> be a good place to use it.</P>
<P><STRONG>Background &amp; Problem</STRONG>&nbsp;</P>
<P>In the article, <A class="" href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp">NHibernate Best Practices with ASP.NET</A>, the <A class="" href="http://www.hibernate.org/43.html">open-session-in-view</A>&nbsp;technique is employed to begin a transaction at the beginning of each HTTP request, and then to commit the transaction at the end of the request.&nbsp; There are a&nbsp;few drawbacks associated with this:</P>
<UL>
<LI>If you don't need a transaction, or if you don't even need to talk to the database, you've wasted a bit of&nbsp;useless transactional&nbsp;overhead.</LI>
<LI>Having transactions automatically started in an HTTP module can unintentionally&nbsp;begin transactions for&nbsp;unintended items such as images and CSS files&nbsp;depending on IIS settings.&nbsp; (This can also be coded around in the HTTP module, but it's still less than ideal IMO.)</LI>
<LI>Since the transaction encompasses the entire HTTP request from start to finish, it's difficult to&nbsp;center&nbsp;the transaction to&nbsp;only a&nbsp;specific section of code.</LI></UL>
<P>On the flip side, using an HTTP module greatly simplifies the process of managing the transaction.&nbsp; A few challenges when not using an HTTP module include:</P>
<UL>
<LI>How can a transaction be started from a project layer without talking to an NHibernate manager class directly?</LI>
<LI>Assume a page communicates with two databases at the same time.&nbsp; How can a transaction be cleanly started for one database communication but not the other?</LI>
<LI>How can the transaction be managed to begin at the start of a particular method and committed at the end of the method, again, without talking to an NHibernate manager class directly?</LI></UL>
<P>The <A class="" href="http://wiki.castleproject.org/index.php/Facility:Automatic_Transaction_Management">Castle Project Automatic Transaction Management facility</A> is about the cleanest approach to transaction management that I have found.&nbsp; With this facility, in conjunction with the <A class="" href="http://wiki.castleproject.org/index.php/Services:Transaction">Castle Project Transaction service</A>, it's simple to mark a class as transactional and a particular method as using a transaction, as demonstrated in the following sample code:</P>
<P><TEXTAREA class=c#:nogutter name=code rows=4 cols=50>[Transactional]
public class EditCustomerPresenter {
[Transaction(TransactionMode.Requires)]
public void Update(long customerId) {
// Do stuff with the DB
}
}</TEXTAREA> </P>
<P>This contest involves brining&nbsp;the benefits of the Automatic Transaction Management facility to the "enterprise" NHibernate sample code included in <A class="" href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp">NHibernate Best Practices with ASP.NET</A>.<STRONG>&nbsp;</STRONG></P>
<P><STRONG>Your Incentive</STRONG></P>
<P>Up for grabs with this contest is the following book.</P>
<P><IMG alt="Design Patterns: Elements of Reusable Object-Oriented Software" src="http://www.awprofessional.com/ShowCover.asp?isbn=0321399838&amp;type=c" width=125></P>
<P><A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321399838&amp;rl=1">Essential Windows Workflow Foundation</A><BR>By Dharma Shukla, Bob Schmidt.</P>
<P>The prize winning code will also be integrated into the NHibernate Best Practices article's "enterprise" sample project with plenty of accolades for the author in the&nbsp;explanatory comments.</P>
<P><STRONG>Instructions to Enter</STRONG></P>
<OL>
<LI>Make sure you have NUnit installed; available at <A href="http://www.nunit.org/" target=_blank>http://www.nunit.org/</A>.</LI>
<LI>Download the NHibernate Best Practice article's <A class="" href="http://www.codeproject.com/aspnet/NHibernateBestPractices/EnterpriseSample.zip">"enterprise" sample code</A>&nbsp;from CodeProject.</LI>
<LI>Follow the <A class="" href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp#EXTENDING_BASICS">steps described in the article</A> to get the sample code up and running.</LI>
<LI>Open NUnit, go to File/Open, then open &lt;solution directory&gt;/EnterpriseSample.Tests/bin/Debug/EnterpriseSample.Tests.dll. Click run and make sure all the tests pass.&nbsp; (You may need to add an assembly redirect for your version of NUnit; an <A class="" href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp?df=100&amp;forumid=278860&amp;noise=5&amp;exp=0&amp;mpp=50&amp;select=2017728#xx2017728xx">example assembly redirect is described in the article's comments</A>.)</LI>
<LI>Complete the&nbsp;integration requirements&nbsp;as described below. Be sure to follow the style of the code that is already in place: classes, methods and public properties in PascalCase, private members in camelCase, etc. Following the style that's already there is always a good rule of thumb when modifying legacy code.</LI>
<LI>When finished with the integration, make sure all the unit tests are still passing and that no test is being ignored, zip up your solution and send to <A href="mailto:challenge4@emccafferty.com">challenge4@emccafferty.com</A>. If you want to submit your code, but don't want to be considered for the prize, please&nbsp;let me know.&nbsp; The due date for your submission is&nbsp;<SPAN style="FONT-WEIGHT:bold;COLOR:red;">Monday morning&nbsp;at 8 AM, May 14, US mountain time</SPAN>.</LI></OL>
<P>The first correct solution which, in my completely subjective opinion, integrates Castle Project in&nbsp;the cleanest and most simple (to use) manner, will win the contest.</P>
<P><STRONG>Now Integrate It!</STRONG></P>
<P>Below is a listing of requirements and/or suggestions for your solution.&nbsp; "Requirements" need to be included in your solution.&nbsp; "Suggestions" need not be&nbsp;implemented exactly as described&nbsp;if you find a better way, in your opinion, to fulfill the stated goals.</P>
<UL>
<LI><EM>Required</EM>:&nbsp; The EnterpriseSample.Presenters.EditCustomerPresenter.Update method must be wrapped within a transaction.&nbsp; This is the ONLY method which needs to have a transaction applied to it.</LI>
<LI><EM>Required</EM>:&nbsp; The transaction&nbsp;may not be started and stopped within the ICustomerDao data-access object.&nbsp; E.g., adding NHibernateSessionManager.BeginTransaction &amp; CommitTransaction to the DAO is not permitted.</LI>
<LI><EM>Required</EM>:&nbsp; The EnterpriseSample.Presenters and EnterpriseSample.Web&nbsp;projects must remain ignorant of NHibernateSessionManager.</LI>
<LI><EM>Required</EM>:&nbsp; The transaction may not be <EM>started</EM> in any&nbsp;IHttpModule, such as&nbsp;ProjectBase.Data.NHibernateSessionModule, the HTTP module which commits any open transactions.&nbsp; But it's OK if this HTTP module is still used to commit any transactions.&nbsp; (You'll note, in the sample code, that the code which would usually start the transaction has been commented out.)</LI>
<LI><EM>Required</EM>:&nbsp; As the EnterpriseSample code is configured to work with multiple databases, your solution must be able to support multiple databases as well.&nbsp; An example would be [Transaction("TheDbsUniqueIdentifier")].&nbsp; This example is only a suggestion and is not required.&nbsp; What <EM>is</EM> required is that an easy way exists to have the transaction started for one database/session factory&nbsp;and not for another.</LI>
<LI><EM>Required</EM>:&nbsp; Unit tests must be included to test your solution.<EM>&nbsp;</EM></LI>
<LI><EM>Suggestion</EM>:&nbsp; Beginning a transaction may be done using an attribute such as [Transaction] or by using aspect oriented programming to intercept the method and begin the transaction.&nbsp; Although not required, the attribute approach would be preferred for the purposes of <A class="" href="http://www.martinfowler.com/ieeeSoftware/explicit.pdf">being explicit</A>.&nbsp; If you use an AOP approach, leverage <A class="" href="http://www.castleproject.org/aspectsharp/index.html">Castle Project's Aspect#</A><EM>.</EM></LI>
<LI><EM>Suggestion</EM>:&nbsp; The transaction&nbsp;may ultimately be started and stopped via the existing ProjectBase.Data.NHibernateSessionManager class.&nbsp; If your solution requires working around the NHibernateSessionManager to support multiple databases, then that's alright.</LI>
<LI><EM>Suggestion</EM>:&nbsp; Castle Project's Automatic Transaction Management facility, or a customized variant, <STRONG><EM>may</EM> be leveraged</STRONG> but is not required.&nbsp; You're certainly welcome to write your own handler code from the ground up.</LI>
<LI><EM>Suggestion</EM>:&nbsp; Your transaction management code for handling the attributes should be placed into the project ProjectBase.Data in a new folder called TransactionMgmt.</LI></UL>
<P>As a bonus, and added brownie points for&nbsp;getting the prize,&nbsp;develop your solution to commit the transaction immediately after&nbsp;the method which has the transaction attribute declared on top of it.&nbsp; So the transaction will begin at the top of&nbsp;the method and&nbsp;commit as soon as the method completes.&nbsp; Your welcome to use various approaches to this including, but not limited to, attributes to commit the transaction and/or aspect oriented programming (AOP) to commit the transaction when the method completes.&nbsp; Again, if you use an AOP approach, leverage <A class="" href="http://www.castleproject.org/aspectsharp/index.html">Castle Project's Aspect#</A>.</P>
<P><STRONG>Why?</STRONG></P>
<P>This challenge has been incredibly fun for me to work on.&nbsp; It's&nbsp;far from trivial&nbsp;and requires you to use a variety of techniques to integrate successfully.&nbsp; Furthermore, Castle Project is a phenomenal grouping of utilities which needs to get greater attention around the development community.&nbsp; Not only can they be used out of the box, but they&nbsp;can also be extended to other purposes...which is&nbsp;one of the challenges here. &nbsp;Consequently, I hope this challenge will give you something fun to work on while learning a few things in the process.</P>
<P><STRONG>Where to go for Help</STRONG></P>
<P>The following resources should help explain the code you'll be working with better along with possible solution paths for you to take:</P>
<UL>
<LI>NHibernate Best Practices article:&nbsp; <A href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp">http://www.codeproject.com/aspnet/NHibernateBestPractices.asp</A></LI>
<LI>Castle Project Facilities:Automatic Transaction Management:&nbsp; <A href="http://wiki.castleproject.org/index.php/Facility:Automatic_Transaction_Management">http://wiki.castleproject.org/index.php/Facility:Automatic_Transaction_Management</A>&nbsp;</LI>
<LI>Castle Project Services:Transaction:&nbsp; <A href="http://wiki.castleproject.org/index.php/Services:Transaction">http://wiki.castleproject.org/index.php/Services:Transaction</A></LI>
<LI>Castle Project Aspect#:&nbsp; <A href="http://www.castleproject.org/aspectsharp/index.html">http://www.castleproject.org/aspectsharp/index.html</A></LI>
<LI>"The joys of Castle.Services.Transaction":&nbsp; <A href="http://jroller.com/page/hammett?entry=the_joys_of_castle_services">http://jroller.com/page/hammett?entry=the_joys_of_castle_services</A></LI>
<LI>Castle Project Forums:&nbsp; <A href="http://forum.castleproject.org/index.php">http://forum.castleproject.org/index.php</A></LI>
<LI>NHibernate Forums:&nbsp; <A href="http://forum.hibernate.org/viewforum.php?f=25">http://forum.hibernate.org/viewforum.php?f=25</A></LI></UL>
<P>Good luck and let me know if you have any questions!</P>
<P>Billy McCafferty</P><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=24285" width="1" height="1">ASP.NETContestsNHibernateCastle ProjectNHibernate Best Practices article updatedhttp://devlicio.us/blogs/billy_mccafferty/archive/2007/05/02/nhibernate-best-practices-article-updated.aspxThu, 03 May 2007 01:24:00 GMT40756a8b-6212-4073-9d98-6c26781577de:24182Billy McCafferty27<p>I&#39;ve updated the CodeProject article <a href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp">NHibernate Best Practices with ASP.NET, 1.2 ed</a> with a number of very important fixes and pedagogical expansions.&nbsp; (I&#39;ve been&nbsp;waiting for an excuse to use that word.)&nbsp; If you&#39;ve been using the sample code as a foundation&nbsp;for your project, these changes will be important to you.&nbsp; Here are a few:</p>
<ul>
<li>Example code has been added to demonstrate using <a href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp#CORE">NHibernate with custom collections</a>.&nbsp; A new page called ListSuppliers.aspx then leverages&nbsp;the custom collection.&nbsp; The article has also been updated to explain the technique.</li>
<li>The <a href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp#BEYOND_BASICS">Model-View-Presenter example has been expanded</a> to include the EditCustomer.aspx page; this page contains three views on a single page with event handling and application flow separated from the views.</li>
<li>Overhauled the DomainObject base class&nbsp;to be in-line&nbsp;with a <a href="http://devlicio.us/blogs/billy_mccafferty/archive/2007/04/25/using-equals-gethashcode-effectively.aspx">previous post concerning the use of Equals and GetHashCode</a>.</li>
<li>NHibernate can return strongly typed lists, natively.&nbsp; The generic DAO, included with the sample, now includes this capability.</li>
<li>Bug:&nbsp; Transaction rollbacks&nbsp;were not previously working.&nbsp; This has been fixed.</li>
<li>Bug:&nbsp; Closing the NHibernate session was not flushing changes made to data.&nbsp; So if you weren&#39;t using a transaction, changes weren&#39;t being committed; this has been fixed.</li>
<li>Date manipulation has been fixed to allow the unit tests to pass in different localizations.</li>
<li>Added support for IIS 7 to work with the HTTP modules.</li>
<li>A number of <a href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp?df=100&amp;forumid=278860&amp;noise=5&amp;exp=0&amp;mpp=50&amp;select=2015705#xx2015705xx">other&nbsp;fixes and enhancements</a> have been included.</li>
</ul>
<p>I&#39;ll be&nbsp;kicking off a <strong>contest later this week</strong> concerning a needed refactoring to the &quot;enterprise&quot; sample code...only the first correct submission will be a winner, so stay tuned to <a href="http://devlicio.us">devlicio.us</a>&nbsp;for details.</p>
<p>Billy McCafferty</p><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=24182" width="1" height="1">ASP.NETNHibernateNHibernate Best Practices with ASP.NET, 1.2nd Ed.http://devlicio.us/blogs/billy_mccafferty/archive/2007/04/03/nhibernate-best-practices-with-asp-net-1-2nd-ed.aspxWed, 04 Apr 2007 00:36:00 GMT40756a8b-6212-4073-9d98-6c26781577de:20565Billy McCafferty10<p>I&#39;m very pleased to announce the release of <a href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp">NHibernate Best Practices with ASP.NET, 1.2<sup>nd</sup> Ed.</a> on CodeProject.com.</p>
<p><strong>Preface to the 1.2<sup>nd</sup> Edition</strong>&nbsp;</p>
<p>In March of 2006 I published my initial thoughts on NHibernate best practices with ASP.NET, generics and unit tests. I&#39;ve been delighted to learn that these ideas have been implemented in a number of real-world scenarios with strong success. Since then, I&#39;ve worked with many people to refine these ideas, learn from mistakes and leverage a more powerful version of NHibernate. Accordingly, although only a modest, yet important, amount of modification has been made to the underlying architecture, some other important factors have been updated and addressed in this article: </p>
<ul>
<li>Quite simply, NHibernate is awesome. In the previous edition of this article, I assumed you already knew this...but I now try to convince the dissenters as well.
</li>
<li>NHibernate 1.2 natively supports generics.
</li>
<li>NHibernate 1.2 natively supports nullable types.
</li>
<li>NHibernate 1.2 natively supports mapping attributes.
</li>
<li>NHibernate 1.2 can communicate with stored procedures.
</li>
<li>Using CallContext for ISession storage in ASP.NET was susceptible to failure under load.
</li>
<li>Exposing a publicly settable ID property created a point-of-susceptibility.
</li>
<li>Providing automatic parent/child wiring, via Ayende&#39;s very helpful NHibernate.Generics, was <a href="http://www.ayende.com/Blog/archive/2006/10/16/7179.aspx">more headache than help</a>.
</li>
<li>Have you used Rhino Mocks 3.0, NUnitAsp, or Fit? Well, these are all discussed with an expanded emphasis on test-driven development.
</li>
<li>As an alternative to my recommendations, also consider <a href="http://www.castleproject.org/">Castle Project&#39;s offerings</a> such as <a href="http://www.castleproject.org/monorail/index.html">MonoRail</a> and/or <a href="http://www.castleproject.org/activerecord/index.html">ActiveRecord</a> for a simple yet powerful out-of-the-box framework for ASP.NET. In fact, if it&#39;s technically feasible and you can generate buy-in on your team for these off-the-shelf tools, I would recommend using them over a ground-up solution. But even if you do use Castle Project facilities, this article should still have a lot of useful information for you!
</li>
<li>In addition to those listed above, there are other important refactorings and fixes throughout the article and the code. This edition is by no means just a light touch-up of the original article.
</li>
<li>In addition to an overhaul of the original sample code, an expanded &quot;enterprise&quot; sample has been included demonstrating:
<ul>
<li>NHibernate with web services
</li>
<li>NHibernate with multiple databases
</li>
<li>Integration with <a href="http://www.castleproject.org/container/index.html">Castle Windsor</a>
</li>
<li>A reusable data layer for the data access components.
</li>
<li>A simple example of Model-View-Presenter </li>
</ul>
</li>
</ul>
<p>I hope this article will be chock full of (at least a couple) good ideas no matter what your level of experience is.&nbsp; I look forward to hearing your experiences with the article and any feedback you may have.&nbsp; I&#39;ve also included some&nbsp;<a href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp#WHAT_NEXT">areas&nbsp;for further research</a>&nbsp;for anyone interested in taking the sample framework further.</p>
<p>Billy McCafferty</p><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=20565" width="1" height="1">ASP.NETNHibernateInject DI Container into Domain Objects with NHibernatehttp://devlicio.us/blogs/billy_mccafferty/archive/2007/02/05/inject-di-container-into-domain-objects-with-nhibernate.aspxTue, 06 Feb 2007 03:52:00 GMT40756a8b-6212-4073-9d98-6c26781577de:9685Billy McCafferty25<P>I've been asked a couple of times how to give a domain object access to a dependency injection (DI) container, such as Castle Windsor, if the domain object is loaded via an ORM, such as NHibernate.&nbsp; There are two apparent ways to do this:&nbsp; 1) you can manually give the domain object access to the DI via "setter injection" from your controller or service layer, or 2) you can use an NHibernate IInterceptor to preset the DI container when the object is loaded from the database.&nbsp; The latter is much cleaner and avoids having to pass service&nbsp;object references through middlemen classes.</P>
<P><STRONG>Disclaimer:</STRONG>&nbsp; I feel I should&nbsp;add a&nbsp;disclaimer to this post that this technique should not&nbsp;be used as standard practice.&nbsp; Giving domain objects direct access to the DI container can be very powerful but also enables the domain layer to take on responsibilities that it should not have.&nbsp; Furthermore, having access to the DI container from the domain layer creates, at the very least,&nbsp;a virtual dependency on everything available via the DI container; consequently, additional maintenance issues may have to be considered.&nbsp; Finally, the DI container itself presents another layer of indirection which can be difficult to&nbsp;easily understand during the maintenance phase of a project.&nbsp; With that said...</P>
<P>Assume you want to show who a customer was referred by but can't set it up in a nice HBM mapping.&nbsp; The only way you can do it, for some reason or another, is by having the Customer instance make an explicit call to the database.&nbsp; Our goals are 1) to keep Customer only dependent on DAO <EM>interfaces</EM> and 2) to automatically inject the DAO dependency to Customer as soon as its loaded from the database even if it's loaded via an ORM.&nbsp; (Obviously, this example is a little strange to begin with but illustrates the technique, nonetheless.&nbsp; The technique is equally applicable for providing other services, such as an email utility.)</P>
<P>If you'd like to walk through modifying an application, already wired for Castle Windsor, to accommodate doing this,&nbsp;download the <A class="" href="http://www.codeproject.com/useritems/ModelViewPresenter/EnterpriseApplicationMvp.zip">"enterprise" sample app</A> found&nbsp;within&nbsp;the <A class="" href="http://www.codeproject.com/useritems/ModelViewPresenter.asp">MVP with ASP.NET article on CodeProject.com</A>&nbsp;and follow the steps below.&nbsp;&nbsp;(Alternatively, you can just download the sample at the end of this post to see the finished product.)&nbsp; You'll need to follow the steps found within the article to get it working with your SQL Server/Northwind database.&nbsp; The modification steps to the sample app are as follows:</P>
<P>1) First, since we always take a test-driven approach (right?), amend MvpSample.Tests.Data.CustomerDaoTests to reflect the following:</P>
<DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;">
<P style="MARGIN:0px;">[<SPAN style="COLOR:#2b91af;">TestFixture</SPAN>]</P>
<P style="MARGIN:0px;">[<SPAN style="COLOR:#2b91af;">Category</SPAN>(<SPAN style="COLOR:#a31515;">"NHibernate Tests"</SPAN>)]</P>
<P style="MARGIN:0px;"><SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">class</SPAN> <SPAN style="COLOR:#2b91af;">CustomerDaoTests</SPAN></P>
<P style="MARGIN:0px;">{</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;summary&gt;</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> Initializes the NHibernate session bound to </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> HttpContext. This TestFixtureSetUp could be </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> moved to a NHibernateUnitTest class so you </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> don't have to </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> copy/past it into every unit test class.</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;/summary&gt;</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; [<SPAN style="COLOR:#2b91af;">TestFixtureSetUp</SPAN>]</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">void</SPAN> Setup() {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">NHibernateSessionManager</SPAN>.Instance</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .RegisterInterceptor(</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">new</SPAN> <SPAN style="COLOR:#2b91af;">NHibernateInterceptor</SPAN>());</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">NHibernateSessionManager</SPAN>.Instance</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .BeginTransaction();</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;summary&gt;</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> Tests successful dependency injection </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> from within the domain layer.</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;/summary&gt;</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; [<SPAN style="COLOR:#2b91af;">Test</SPAN>]</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">void</SPAN> TestGetReferrer() {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">IDaoFactory</SPAN> daoFactory = </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">new</SPAN> <SPAN style="COLOR:#2b91af;">NHibernateDaoFactory</SPAN>();</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">ICustomerDao</SPAN> customerDao = </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; daoFactory.GetCustomerDao();</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">Customer</SPAN> foundCustomer = </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; customerDao.GetById(<SPAN style="COLOR:#a31515;">"CHOPS"</SPAN>, <SPAN style="COLOR:blue;">false</SPAN>);</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">Customer</SPAN> referrer = </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; foundCustomer.GetReferrer();</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">Assert</SPAN>.AreEqual(<SPAN style="COLOR:#a31515;">"Folies gourmandes"</SPAN>, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; referrer.CompanyName);</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; }</P></DIV>
<P>... remainder of pre-existing tests... </P>
<P>In the above code, you can see that we're doing two new things.&nbsp; First, we've added the call to RegisterInterceptor to the Setup method.&nbsp; (Since you have to register interceptors <EM>before</EM> starting a transaction, the order is important here.)&nbsp; So, as the code implies, we can wire up container DI via a custom, NHibernate Interceptor.&nbsp; The second thing to note is the new test.&nbsp; We'll be adding the method GetReferrer, which will&nbsp;use the DI container,&nbsp;to the Customer&nbsp;class.</P>
<P>2) If you try to compile the above change, VS will initially complain about the missing NHibernate interceptor class.&nbsp; So add a new class called NHibernateInterceptor and at it to the MvpSample.Data package.&nbsp; Since it's specific to the data layer - and to NHibernate for that matter -&nbsp;the data layer is&nbsp;the appropriate place to put it.&nbsp; The class is defined as follows:</P>
<DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;">
<P style="MARGIN:0px;"><SPAN style="COLOR:blue;">namespace</SPAN> MvpSample.Data</P>
<P style="MARGIN:0px;">{</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">class</SPAN> <SPAN style="COLOR:#2b91af;">NHibernateInterceptor</SPAN> : <SPAN style="COLOR:#2b91af;">IInterceptor</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">bool</SPAN> OnLoad(<SPAN style="COLOR:blue;">object</SPAN> entity, <SPAN style="COLOR:blue;">object</SPAN> id, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">object</SPAN>[] state, <SPAN style="COLOR:blue;">string</SPAN>[] propertyNames, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">IType</SPAN>[] types)</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// Only use "setter injection" to give objects</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// that implement IUsesDependencyInjection a </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// reference to the DI container.</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">if</SPAN> (<SPAN style="COLOR:blue;">typeof</SPAN>(<SPAN style="COLOR:#2b91af;">IUsesDependencyInjection</SPAN>)</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .IsInstanceOfType(entity)) {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ((<SPAN style="COLOR:#2b91af;">IUsesDependencyInjection</SPAN>) entity)</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .DependencyInjectionContainer =</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">new</SPAN> <SPAN style="COLOR:#2b91af;">WindsorContainer</SPAN>(<SPAN style="COLOR:blue;">new</SPAN> <SPAN style="COLOR:#2b91af;">XmlInterpreter</SPAN>());</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// Even though we gave the object it's DI </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// container, return the fact that we </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// didn't modify the persistent properties</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">return</SPAN> <SPAN style="COLOR:blue;">false</SPAN>;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">bool</SPAN> OnFlushDirty(<SPAN style="COLOR:blue;">object</SPAN> entity, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">object</SPAN> id, <SPAN style="COLOR:blue;">object</SPAN>[] currentState, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">object</SPAN>[] previousState, <SPAN style="COLOR:blue;">string</SPAN>[] propertyNames, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">IType</SPAN>[] types)</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// Return the fact that we didn't </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// modify the entity</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">return</SPAN> <SPAN style="COLOR:blue;">false</SPAN>;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">bool</SPAN> OnSave(<SPAN style="COLOR:blue;">object</SPAN> entity, <SPAN style="COLOR:blue;">object</SPAN> id, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">object</SPAN>[] state, <SPAN style="COLOR:blue;">string</SPAN>[] propertyNames, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">IType</SPAN>[] types)</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// Return the fact that we didn't </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// modify the entity</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">return</SPAN> <SPAN style="COLOR:blue;">false</SPAN>;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">void</SPAN> OnDelete(<SPAN style="COLOR:blue;">object</SPAN> entity, <SPAN style="COLOR:blue;">object</SPAN> id, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">object</SPAN>[] state, <SPAN style="COLOR:blue;">string</SPAN>[] propertyNames, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">IType</SPAN>[] types) {}</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">void</SPAN> PreFlush(<SPAN style="COLOR:#2b91af;">ICollection</SPAN> entities) {}</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">void</SPAN> PostFlush(<SPAN style="COLOR:#2b91af;">ICollection</SPAN> entities) {}</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">object</SPAN> IsUnsaved(<SPAN style="COLOR:blue;">object</SPAN> entity) {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">return</SPAN> <SPAN style="COLOR:blue;">null</SPAN>;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">int</SPAN>[] FindDirty(<SPAN style="COLOR:blue;">object</SPAN> entity, <SPAN style="COLOR:blue;">object</SPAN> id, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">object</SPAN>[] currentState, <SPAN style="COLOR:blue;">object</SPAN>[] previousState, </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">string</SPAN>[] propertyNames, <SPAN style="COLOR:#2b91af;">IType</SPAN>[] types) {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">return</SPAN> <SPAN style="COLOR:blue;">null</SPAN>;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">object</SPAN> Instantiate(<SPAN style="COLOR:#2b91af;">Type</SPAN> type, <SPAN style="COLOR:blue;">object</SPAN> id) {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">return</SPAN> <SPAN style="COLOR:blue;">null</SPAN>;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">}</P></DIV>
<P>The only bit of interesting code is found within the method OnLoad.&nbsp; This method first checks to see if the persistent object being loaded implements the interface IUsesDependencyInjection and then sets the publicly accessible property to give the object a reference to the Castle Windsor container.&nbsp; This is also called "setter injection."</P>
<P>3) The next logical step is to define the IUsesDependencyInjection interface.&nbsp; This will be implemented by our persistent business objects which should have a reference to the DI container when they're loaded from the database.&nbsp; The interface will be added to the MvpSample.Core project since the business objects will be implementing it.&nbsp; The simple interface is as follows:</P>
<DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;">
<P style="MARGIN:0px;"><SPAN style="COLOR:blue;">namespace</SPAN> MvpSample.Core.DataInterfaces</P>
<P style="MARGIN:0px;">{</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:blue;">interface</SPAN> <SPAN style="COLOR:#2b91af;">IUsesDependencyInjection</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">IWindsorContainer</SPAN> DependencyInjectionContainer {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">set</SPAN>; </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">get</SPAN>;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">}</P></DIV>
<P>4) Now modify MvpSample.Core.Domain.Customer to implement this interface.&nbsp; It'll immediatly complain that Custom needs to implement the getter/setter from the interface.&nbsp; You have a choice here; you can either implement the code in the Customer class itself, or, you can add it to the persistent object super class called DomainObject.&nbsp; (I.e. All persistent objects inherit from this class in the sample project.)&nbsp; I chose to put the implementation details into DomainObject for two reasons:&nbsp; A) it's now reusable without any duplicated code and exposes a very handy public setter for all persistent classes and B) you can place pre-condition code in the getter to ensure that the DI container has been set before it's used.&nbsp; The latter point will avoid any unexpected "object reference was null" exceptions.&nbsp; The downside to putting it into DomainObject is that it exposes a lot more power to a lot more classes.&nbsp; So this should be avoided if it's only going to be used by a couple of objects.&nbsp; (Regardless,&nbsp;DomainObject shouldn't inherit from IUsesDependencyInjection, only Customer should, at this time; otherwise, the interceptor will automatically give every persistent object a reference to the container...which might not be a terrible thing in some situations.)&nbsp; So in the DomainObject class, we add:</P>
<DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;">
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;summary&gt;</SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> Publicly accessible to allow the dependency </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> injection container to be given to the object.&nbsp; </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> If you have your domain object implement </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;see cref="IUsesDependencyInjection" /&gt;</SPAN><SPAN style="COLOR:green;">, </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> it'll automatically be wired up with the DI </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> container when loaded with the ORM. If </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> someone&nbsp; has switched out the ORM or </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> disabled this, then the container can still </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> be set via this property.</SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;/summary&gt;</SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:#2b91af;">IWindsorContainer</SPAN> DependencyInjectionContainer {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">set</SPAN> {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dependencyInjectionContainer = <SPAN style="COLOR:blue;">value</SPAN>;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">get</SPAN> {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">if</SPAN> (dependencyInjectionContainer == <SPAN style="COLOR:blue;">null</SPAN>) </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">throw</SPAN> <SPAN style="COLOR:blue;">new</SPAN> <SPAN style="COLOR:#2b91af;">ApplicationException</SPAN>(</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#a31515;">"dependencyInjectionContainer has not "</SPAN> +</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#a31515;">"yet been initialized"</SPAN>);</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">return</SPAN> dependencyInjectionContainer;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">}</P></DIV>
<P>5)&nbsp;The only remaining piece, to get the unit test working, is to add the GetReferrer method to Customer:</P>
<DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;">
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;summary&gt;</SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> This is an example of using DI from </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> the domain layer itself.</SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;/summary&gt;</SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:#2b91af;">Customer</SPAN> GetReferrer() {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// Obviously, hard-coding "FOLIG" is </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// unrealistic...but it'll work to illustrate</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// the use of a DI container from within the </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// domain layer.</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">return</SPAN> ((<SPAN style="COLOR:#2b91af;">IDaoFactory</SPAN>) </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DependencyInjectionContainer[<SPAN style="COLOR:blue;">typeof</SPAN>(<SPAN style="COLOR:#2b91af;">IDaoFactory</SPAN>)])</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .GetCustomerDao().GetById(<SPAN style="COLOR:#a31515;">"FOLIG"</SPAN>, <SPAN style="COLOR:blue;">false</SPAN>);</P>
<P style="MARGIN:0px;">}</P></DIV>
<P>6) The NUnit test that we wrote previously should now compile and run successfully.&nbsp; (Be sure to copy the web's Config folder into the MvpSample.Tests/bin/Debug so the unit test will find it.&nbsp; A post-compilation&nbsp;script would be good for doing this on future builds.)</P>
<P>7) Now that we have the unit test working successfully, all we have to do is modify the NHibernateSessionModule (an IHttpModule) to register the interceptor when the transaction-per-web-request is started:</P>
<DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;">
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;summary&gt;</SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> Opens a session within a transaction at the </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> beginning of the HTTP request. This doesn't </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> actually open a connection to the database </SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> until needed.</SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:gray;">///</SPAN><SPAN style="COLOR:green;"> </SPAN><SPAN style="COLOR:gray;">&lt;/summary&gt;</SPAN></P>
<P style="MARGIN:0px;"><SPAN style="COLOR:blue;">private</SPAN> <SPAN style="COLOR:blue;">void</SPAN> BeginTransaction(<SPAN style="COLOR:blue;">object</SPAN> sender, <SPAN style="COLOR:#2b91af;">EventArgs</SPAN> e) {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// This needs to be called BEFORE begin </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// transaction since an interceptor can't</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// be registered after a session has been </SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:green;">// created.</SPAN></P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">NHibernateSessionManager</SPAN>.Instance</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .RegisterInterceptor(<SPAN style="COLOR:blue;">new</SPAN> <SPAN style="COLOR:#2b91af;">NHibernateInterceptor</SPAN>());</P>
<P style="MARGIN:0px;">&nbsp;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:#2b91af;">NHibernateSessionManager</SPAN>.Instance</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .BeginTransaction();</P>
<P style="MARGIN:0px;">}</P></DIV>
<P>Obviously, you don't <EM>have</EM> to use a transaction for this to work, but it shows how an interceptor works when a transaction is being used.</P>
<P>8) To see it all in action, add a lblReferredBy label to the web project page found at /Views/EditCustomerView.ascx and set its text value to the referrer from within the set property of CustomerToUpdate, found within its code-behind page:</P>
<DIV style="FONT-SIZE:10pt;BACKGROUND:white;OVERFLOW:auto;COLOR:black;FONT-FAMILY:Courier New;">
<P style="MARGIN:0px;"><SPAN style="COLOR:blue;">public</SPAN> <SPAN style="COLOR:#2b91af;">Customer</SPAN> CustomerToUpdate {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">get</SPAN> { ...&nbsp;}</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">set</SPAN> {</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lblReferredBy.Text = </P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <SPAN style="COLOR:blue;">value</SPAN>.GetReferrer().CompanyName;</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...</P>
<P style="MARGIN:0px;">&nbsp;&nbsp;&nbsp; }</P>
<P style="MARGIN:0px;">}</P></DIV>
<P>That's it in a nutshell.&nbsp; The process goes as follows:</P>
<OL>
<LI>
<DIV>Web request gets sent to server.</DIV></LI>
<LI>
<DIV>NHibernateSessionModule creates the interceptor, registers it with the Open-Session-in-View session and begins a transaction.</DIV></LI>
<LI>
<DIV>Page loads a persistent object from the database.</DIV></LI>
<LI>
<DIV>NHibernateInterceptor checks to see if the object being loaded implements IUsesDependencyInjection and sets its DI container, accordingly.</DIV></LI>
<LI>
<DIV>Other code calls the method GetReferrer, found on the Customer object.&nbsp; GetReferrer uses the DI container to load another Customer from the database via a data-access object.&nbsp; But before it's loaded, the getter method of the DI container ensures that&nbsp;the DI container is available for use and throws an exception if not.&nbsp;</DIV></LI></OL>
<P>This tutorial has shown how to give a domain object a reference to a DI container if that object was loaded from the database using NHibernate.&nbsp; The attached sample is a working version of all the steps mentioned above.</P>
<P>As always, please let me know if you have any comments, questions or suggestions.</P>
<P>Billy</P><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=9685" width="1" height="1">C#ASP.NETNHibernateInterested in a book on NHibernate with ASP.NET?http://devlicio.us/blogs/billy_mccafferty/archive/2006/11/28/interested-in-a-book-on-nhibernate-with-asp-net.aspxWed, 29 Nov 2006 01:23:00 GMT40756a8b-6212-4073-9d98-6c26781577de:838Billy McCafferty25<P><SPAN class=postbody>There&nbsp;are a few Java/Hibernate books out there, a&nbsp;couple&nbsp;chapters here and there on .NET/NHibernate, but a glaring&nbsp;vacuum&nbsp;for published material concerning the&nbsp;development of&nbsp;ASP.NET/NHibernate applications, specifically.&nbsp; ASP.NET certainly has plenty of special cases when it comes to integrating NHibernate and a book dedicated to the subject&nbsp;seems warranted.<BR><BR><SPAN class=postbody>I'm not implying anything by this&nbsp;post's title...but just assume, for a moment, hypothetically of course, that a book were in the works for using NHibernate with ASP.NET...&nbsp; </SPAN>A short sampling of topics would include&nbsp;getting started with&nbsp;NHibernate (including the 80% of NHibernate that you use regularly), unit testing with NUnit and FitNesse, generics, open-session-in-view, passive view &amp; supervising controller (model-view-presenter), multiple databases,&nbsp;usage of&nbsp;interceptors, web services, advanced topics, many others...and most importantly...putting it all together.&nbsp;<BR><BR>1) Would this interest you?&nbsp;&nbsp;Would you, instead,&nbsp;be more interested&nbsp;in a book concerning NHibernate with .NET 3.0?<BR><BR>2) What other ASP.NET/NHibernate topics, or areas of difficulty, would you want covered? Personalization, membership, web parts, etc?</SPAN></P>
<P><SPAN class=postbody>3) Finally, what type of&nbsp;book&nbsp;flow&nbsp;works best for you?&nbsp; An assortment of design&nbsp;ideas such as <A class="" href="http://www.martinfowler.com/books.html#eaa">Patterns of Enterprise Application&nbsp;Architecture</A> or <A class="" href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321125215&amp;redir=1&amp;rl=1">Domain Driven Design</A>; a start to finish&nbsp;application-building&nbsp;book such as <A class="" href="http://www.pragmaticprogrammer.com/title/rails1/index.html">Agile Web Development with Rails</A> or <A class="" href="http://www.wrox.com/WileyCDA/WroxTitle/productCd-0764584642.html">ASP.NET 2.0 Website Programming</A>; or somewhere in between like <A class="" href="http://www.awprofessional.com/bookstore/product.asp?isbn=0321268202&amp;rl=1">Applying Domain-Driven Design and Patterns</A>?</SPAN></P>
<P><SPAN class=postbody>Thanks for any feedback you can provide!</SPAN></P>
<P><SPAN class=postbody>Billy</SPAN></P><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=838" width="1" height="1">ASP.NETNHibernate(My) Default ASP.NET Architecturehttp://devlicio.us/blogs/billy_mccafferty/archive/2006/10/05/_2800_My_2900_-Default-ASP.NET-Architecture.aspxThu, 05 Oct 2006 19:56:00 GMT40756a8b-6212-4073-9d98-6c26781577de:224Billy McCafferty22<p>In developing any software application, it&#39;s important to keep things as simple as possible and add complexity only when needed.&nbsp; (I spoke about this in a previous post, <a target="_blank" href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/09/20/Planning-for-vs.-Reacting-to-Change.aspx" title="Planning for vs. Reacting to Change">Planning for vs. Reacting to Change</a>.)&nbsp; On the flip-side, a certain amount of architecture&nbsp;may be&nbsp;assumed at the start of a project depending on the type of&nbsp;application being developed.&nbsp; Selecting an <em>appropriate</em>,&nbsp;default architecture&nbsp;provides your application&nbsp;with a solid foundation and&nbsp;offers&nbsp;guidance for other developers, and yourself, for further development.&nbsp;&nbsp;This entry describes a&nbsp;suggested, default architecture for data-driven, ASP.NET applications for both individual and team development.&nbsp; <em>Disclaimer</em>:&nbsp; it is important to note that there are many appropriate architectural foundations and this is just one of them.</p>
<p><strong>Architectural&nbsp;Assumptions</strong></p>
<p>In providing an architectural approach,&nbsp;some&nbsp;assumptions are made concerning the project goals.&nbsp; These assumptions should be used as a litmus test to determine if the described architecture&nbsp;may be an appropriate fit for your ASP.NET application.</p>
<ul>
<li>Testability is of utmost importance.&nbsp; If&nbsp;test-driven development (TDD) will not be&nbsp;practiced, then most of what follows becomes a moot point.</li>
<li>Separation of concerns is strongly enforced.&nbsp; This policy is enforced using separate, physical assemblies which communicate with each-other via dependency-inversion with interfaces.</li>
<li>Presentation and business logic layers are &quot;data-layer agnostic&quot; as much as reasonably possible.&nbsp; Like the previous point, this&nbsp;is more for testability than it is for the&nbsp;expectation that the data-layer will be&nbsp;actually switched out at a later time.&nbsp; The phrase &quot;reasonably possible&quot; is mentioned because there&nbsp;is&nbsp;often an unavoidable amount&nbsp;of implicit, data-layer assumptions built into both the&nbsp;presentation&nbsp;and business logic layers.&nbsp;&nbsp;For example, if the data-layer uses proxies to watch for an &quot;is-dirty&quot; state, as NHibernate does, then the business layer need not concern itself with these details; but switching to&nbsp;a less-autonomous&nbsp;data-layer may force the business layer to take on this responsibility.&nbsp; Certainly, with enough effort, the business layer could become completely data-layer agnostic; but in most cases, the extra effort isn&#39;t worth the added cost of&nbsp;premature generalization.</li>
<li>NHibernate is used as the data-layer ORM.&nbsp; A data-access object (DAO) abstract factory pattern&nbsp;is employed to easily switch between production and &quot;mock&quot; DAOs for unit-testing.&nbsp;</li>
<li>Model-View-Presenter (MVP) is optionally employed to keep code-behind pages as part of the view, pure and simple.&nbsp;&nbsp;MVP is the simplest solution I have found for making ASP.NET code-behind logic more maintainable and testable.&nbsp;&nbsp;But MVP comes with a cost -&nbsp;it adds another layer of indirection and complexity to the application; therefore, the &quot;Presenters&quot; layer (the &quot;P&quot; in MVP) may be considered as an optional piece to the suggested architecture.&nbsp; Furthermore, the benefits of MVP may be employed later in the project life-cycle, when warranted, without having to modify the existing presentation layer.&nbsp; (Martin Fowler has <a target="_blank" href="http://www.martinfowler.com/eaaDev/ModelViewPresenter.html">suggested</a> that MVP be split into <a target="_blank" href="http://www.martinfowler.com/eaaDev/SupervisingPresenter.html">Supervising Controller</a> and <a href="http://www.martinfowler.com/eaaDev/PassiveScreen.html">Passive View</a>.&nbsp; What&#39;s described below is consistent with Supervising Controller.)</li>
</ul>
<p><strong>In a Nutshell</strong></p>
<p>Below is a graphical summary of the architecture.</p>
<p><img border="0" align="middle" width="600" src="http://www.codeproject.com/KB/architecture/ModelViewPresenter/ApplicationArchitecture.gif" alt="Application Architecture" height="649" style="width:600px;height:649px;" title="Application Architecture" /></p>
<p>In the above diagram, each raised box represents a distinct specialization of the application. Each gray box then represents a separate, physical assembly; e.g. MyProject.Web.dll, MyProject.Presenters.dll, MyProject.Core.dll, etc. The arrows represent assembly dependencies. For example, the <em>.Web</em> assembly depends on the <em>.Presenters</em> and <em>.Core</em> assemblies.</p>
<p>The assemblies avoid bi-directional dependency using the techniques &quot;Dependency Inversion&quot; and &quot;Dependency Injection.&quot;&nbsp; (&quot;DI&quot; in the diagram should be read as &quot;dependency injection.&quot;)&nbsp; To illustrate, note that the <em>.Core</em> assembly contains,&nbsp;along with&nbsp;domain objects, the DAO <em>interfaces</em>.&nbsp; The <em>.Data</em> assembly&nbsp;contains classes which&nbsp;inherit from these interfaces to define the DAO <em>implementations</em>.&nbsp; The <em>.Core</em> assembly&nbsp;is then given its DAO dependencies from another layer, such as&nbsp;from <em>.Presenters</em> or <em>.Tests.</em>&nbsp; Furthermore, another &quot;service layer&quot; could be employed to centralize the DAO-creation services.&nbsp; (Martin Fowler discusses the service-layer approach in <span style="text-decoration:underline;">Patterns of Enterprise Application Architecture</span>.)&nbsp; One approach that I&#39;ve had success with is leveraging the <a target="_blank" href="http://www.castleproject.org/index.php/Windsor_Container" title="Castle Windsor">Castle Windsor</a>&nbsp;project to inject DAO dependencies.&nbsp; Note that this third party tool adds another layer of complexity to the application and should be carefully considered before use (aka &quot;<a target="_blank" href="http://www.google.com/search?hl=en&amp;q=happy+fun+ball" title="happy fun ball">happy fun ball</a>&quot;).</p>
<p><strong>Implementation Details</strong></p>
<p>In all seriousness, an entire&nbsp;book could be written to describe the preceding diagram in full detail.&nbsp; What follows are a number of articles which explain the architecture in greater depth.&nbsp; (Warning:&nbsp; utterly <em>shameless</em> plugs for articles I&#39;ve written!)</p>
<p><em>Dependency Injection for Loose Coupling</em>:&nbsp; <a href="http://www.codeproject.com/cs/design/DependencyInjection.asp">http://www.codeproject.com/cs/design/DependencyInjection.asp</a>.&nbsp;&nbsp;As mentioned previously, the architecture&nbsp;uses dependency injection (DI) throughout the application to keep the application layers loosely coupled.&nbsp; This article&nbsp;offers a&nbsp;simplified overview of the technique - it assumes&nbsp;DI is being performed from one layer to another layer.&nbsp; For a more complete discussion of Dependency Injection, or more cryptically called &quot;Inversion of Control,&quot; be sure to read Martin Fowler&#39;s <a target="_blank" href="http://www.martinfowler.com/articles/injection.html">article on the subject</a>.&nbsp; Fowler&#39;s article also goes into greater&nbsp;depth of using DI &quot;containers.&quot;</p>
<p><em>NHibernate Best Practices with ASP.NET</em>:&nbsp; <a href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp">http://www.codeproject.com/aspnet/NHibernateBestPractices.asp</a>.&nbsp; This audaciously named article gives a good overview of the abstract data-access-object factory used within the architecture and how it&#39;s used with test-driven development.&nbsp; This article includes&nbsp;many details of the suggested architecture, sans the inclusion of MVP and Castle Windsor.</p>
<p><em>Using NHibernate with Multiple Databases</em>:&nbsp; <a href="http://www.codeproject.com/useritems/NHibernateMultipleDBs.asp">http://www.codeproject.com/useritems/NHibernateMultipleDBs.asp</a>.&nbsp; If your project requires communications with multiple databases, then this article provides an&nbsp;extension to the previous NHibernate article.&nbsp; There is very little, published content concerning this subject and I am open to hearing alternative approaches.</p>
<p><em>Model-View-Presenter with ASP.NET</em>:&nbsp; <a href="http://www.codeproject.com/aspnet/ModelViewPresenter.asp">http://www.codeproject.com/aspnet/ModelViewPresenter.asp</a>.&nbsp; There are many resources available for learning about MVP; the emphasis here is with ASP.NET and a variant I call &quot;User-Control as View.&quot;&nbsp;&nbsp;The Model-View-Presenter pattern&nbsp;<em>may</em> be&nbsp;employed in the architecture to allow code to be unit-tested that would usually have been found in the code-behind pages.&nbsp; The downloadable sample &ldquo;MVP Enterprise Solution,&rdquo; found within the article,&nbsp;includes a working example of using the Castle Windsor project within ASP.NET.&nbsp; As noted previously, both MVP and the Castle Windsor project add additional layers of complexity to the application and should only be employed if their benefits of maintainability and testability are warranted in your environment.</p>
<p><strong>Parting Thoughts</strong></p>
<p>There is no single best-practice for architecting ASP.NET, web applications; but, after taking described assumptions into account, what I&#39;ve described may serve as a solid, default architecture for future project work.&nbsp; At the very least, it&nbsp;provides a pool of ideas for consideration.&nbsp; As always, I&#39;m open to thoughts, rebuttals, criticisms and suggestions and welcome your comments.</p>
<p>Billy</p><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=224" width="1" height="1">ArchitectureSoftware DevelopmentASP.NETDevelopment