Introducing ASP by linxiaoqin

VIEWS: 33 PAGES: 29

									                                             S#arp Architecture
                         ASP.NET MVC Best Practices with NHibernate
                                                         Version 0.8.0

Preparing the Development Environment........................................................................... 2
  Installing and Configuring Prerequisites ........................................................................ 2
  Configuring IIS 7 for ASP.NET MVC ........................................................................... 2
  Configuring IIS 6 for ASP.NET MVC ........................................................................... 2
Examining the Northwind Example Project ....................................................................... 3
  Setting up the Northwind Example Project .................................................................... 3
  Examining the Project Tiers............................................................................................ 3
    Northwind.Core: The Domain Layer and the “M” in MVC ...................................... 3
    Northwind.Controllers: The “C” in MVC ................................................................. 4
    Northwind.Data: The Data Layer .............................................................................. 5
    Northwind.Tests: The Unit Testing Layer ................................................................. 6
    Northwind.Web: The “V” in MVC ............................................................................ 6
  Examining the Reusable Class Libraries ........................................................................ 6
    SharpArch.Core .......................................................................................................... 6
    SharpArch.Data ........................................................................................................... 6
    SharpArch.Web ........................................................................................................... 7
  Developing with the Base Architecture Exercise ........................................................... 7
    Test Driven Development Cycle ................................................................................. 7
    Developing the Staff Member Domain Model ........................................................... 8
    Enabling the Domain for Comparisons and Persistence ........................................... 10
    Developing the Controller to Retrieve and Display Results ..................................... 12
    Retrieving Results via a Custom DAO ..................................................................... 17
    Showing the Results in a View ................................................................................. 23
    What Was Accomplished? ........................................................................................ 25
S#arp Architecture Best Practices ..................................................................................... 25
  Within the Web Layer ................................................................................................... 26
    When using ASPX views .......................................................................................... 26
    Configuring web.config ............................................................................................ 26
    Managing Ninject Modules....................................................................................... 26
  Within the Controllers Layer ........................................................................................ 26
  Within the Tests Layer .................................................................................................. 27
  Managing Solution Items .............................................................................................. 27
  NHibernate .................................................................................................................... 27
  Microformats................................................................................................................. 27
Common Development Problems & Exceptions .............................................................. 28
  Exception Troubleshooting ........................................................................................... 28
Appendix A: Resources ................................................................................................... 28
  Referenced Works ......................................................................................................... 28
Preparing the Development Environment
Installing and Configuring Prerequisites
   1. Install Visual Studio 2008. After installing VS 2008, set auto-formatting options
      appropriately:
          a. go to Tools / Options and check “Show all settings”
          b. Expand Text Editor / C# / Formatting / New Lines and uncheck the
              following:
                     Place open brace on new line for methods
                     …for anonymous methods
                     …for control blocks
                     …for anonymous types
                     …for object initializers
                     …for lambda expressions
          c. Expand Text Editor / HTML:
                     Under Validation, set target to “XHTML 1.1”
                     Under Miscellaneous:
                         1. Uncheck “Auto ID elements on paste in Source view”
                         2. Check “Format HTML on paste”
   2. Install ASP.NET MVC Preview 5 (see the ASP.NET MVC Preview Release
      Notes if you’re upgrading from a previous version). This need not be installed on
      production environments as only the DLLs need to be deployed.
   3. Install NUnit 2.4.7 for .NET 2.0
   4. Download NHibernate-2.0.0.GA-bin.zip and copy “\NHibernate-2.0.0.GA-bin\
      *.xsd” to "C:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas" to enable
      NHibernate intellisense.

Configuring IIS 7 for ASP.NET MVC
   1. The easiest way to configure IIS 7 for the ASP.NET MVC sample project, is to
      modify IIS 7 to behave in classic mode for the configured virtual directory. To do
      so, first make sure the virtual directory has been given an application name; then
      set the application pool for it to the “classic mode” application pool.

Configuring IIS 6 for ASP.NET MVC
After installing ASP.NET MVC, IIS 6 still needs to be configured as follows:

   1.   Open IIS Mangaement Console
   2.   Expand your computer
   3.   Expand Websites
   4.   Right-click the website you'd like to edit (Most times it'll be called "Default Web
        Site") and click Properties
   5.   Click the Home Directory tab
   6.   Click Configuration...
   7.   Click Add
   8.   Executable: c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll
   9. Extension: .mvc
   10. Verbs: Limit to: GET,HEAD,POST,DEBUG
   11. Un-check Verify that file exists
   12. Click Ok

Examining the Northwind Example Project
Setting up the Northwind Example Project
   1. Unzip the SharpArchitecture release zip which will include the example project;
      this will create the folders NorthwindSample and SharpArch.
   2. Open the VS 2008 solution file at <unzip
      location>\NorthwindSample\Northwind.sln
   3. Modify the connection string in Northwind.Web/web.config to point to a
      Northwind database. (It's currently configured for working with SQL Server
      2005.)
   4. Compile the solution.
   5. Open NUnit and have it open <unzip
      location>\NorthwindSample\Northwind.Tests\bin\Debug\Northwind.Tests.dll and
      run the tests. They should all pass.
   6. In IIS, create a new virtual directory called NorthwindMvc which points to the
      folder Northwind.Web.
   7. Open a browser and go to http://localhost/NorthwindMvc/Customers.mvc/List to
      see all of the project elements in action including controller injection of data
      access object and NHibernate lazy loading. (Also hit F5 to run the sample in
      debug mode from VS 2008.)
   8. Go to the homepage at http://localhost/NorthwindMvc/Home.mvc to access other
      pages within the sample site.

Examining the Project Tiers
Northwind.Core: The Domain Layer and the “M” in MVC

Custom Collections
Without the proper approach, custom collections can be tricky with NHibernate. As
NHibernate can only communicate with interfaces when loading a collection onto an
object, it’s not possible to trivially bind to e.g. MyCustomerCollection which implements
an IList. Instead, it’s simplest to bind a collection loaded by NHibernate directly to an
IList and then to use extension methods, as described next, to extend the collection’s
functionality with custom methods.

Also note, by looking at Customer.Orders, that collections bound by NHibernate should
be initialized to a new list within the constructor and have a protected setter on the
property itself. This serves two benefits:
     The collection will never be null. Because the collection is initialized during
        construction and cannot be set directly, checking for a null value is unnecessary;
        this avoids any “null object reference” exceptions and keeps the code clean.
        If NHibernate loads the collection onto the object, it will keep track of the
         reference to the collection. Accordingly, the reference to the collection itself
         should not be replaced to avoid problems. It’s fine to use methods such as Clear()
         to manipulate the collection, but it shouldn’t be replaced altogether; therefore,
         having the setter be protected takes a step to ensure this.

Northwind.Core.OrdersExtensions is an example of adding a custom method to a
NHibernate bound collection; e.g., IList<Order>. This removes the complexity of other
alternatives to managing custom collection with NHibernate. (Some more complicated
alternatives, which are compatible with .NET 2.0 and do not require extension methods,
are described at http://devlicio.us/blogs/billy_mccafferty/archive/2007/12/03/custom-
collections-with-nhibernate-part-i-the-basics.aspx.)

Northwind.Controllers: The “C” in MVC
This layer contains all of the controller classes which handle HTTP requests before
displaying a view. With S#arp Architecture, there are two key points to note in the
controllers layer: controllers depend only on service object interfaces, and database
transactions are managed with a transaction attribute.

Dependency Injection of Service Objects
A controller class should never have a direct dependency on a service object; e.g., a data
access object. Instead, controller classes should only depend on service object interfaces.
A dependency injection mechanism is used to inject the concrete instances into the
controller at runtime. S#arp Architecture uses the lightweight, dependency injection
library Ninject for handling this responsibility. To maintain a clean separation to the
dependency injection mechanism, the controller classes are unaware what tool is
performing the dependency injection; they only need to specify what dependencies are
required via the constructor parameters; i.e., the Northwind.Controllers assembly has no
reference to the Ninject library. As an example, the Northwind.Controllers/Categories.cs
class defines the needed dependency, in this case IDao<Category> within the constructor.
Ninject handles determining the appropriate concrete object to pass to the constructor at
runtime. The primary benefits include promotion of a loosely coupled design and
facilitation of easy unit testing with test doubles.

The snippet below demonstrates defining a controller’s dependencies via its constructor:
public class CategoriesController : Controller
{
    public CategoriesController(IDao<Category> categoryDao) {
        this.categoryDao = categoryDao;
    }

        private readonly IDao<Category> categoryDao;
}

Transaction Management
A challenge arises when transactions are used to wrap data manipulations activities
within an action method into a single transaction. A possible solution is to
programmatically start the transaction at the beginning of the action method and to
commit/rollback the transaction at the end of the action method. The drawbacks to this
include making the controller aware of the data access mechanism (we’d rather it be
completely agnostic) and introducing data communication logic into the controllers layer.
This latter point breaks the separation of concerns that we work so hard to maintain. To
accommodate transactions while keeping the controllers layer data access agnostic, an
ASP.NET MVC action filter attribute is provided to open a transaction at the beginning
of an action method and to commit/rollback the transaction at the end of the transaction.
An example usage is found above the method
Northwind.Controllers.CategoriesController.Create(). Note that by default you must use
a transaction attribute above any controller method which will cause changes to the
database.

The following shows an example of using the transaction attribute on a controller action:
[Transaction]
public ActionResult Create(string categoryName) {
    Category category = new Category(categoryName);
    category = categoryDao.SaveOrUpdate(category);

     return View(category);
}

The transaction attribute is provided within the SharpArch.Web library.

Northwind.Data: The Data Layer
When compared to the NBP article (see references Appendix), these updated architectural
guidelines remove much complexity; there's no DaoFactory in S#arp Architecture and it's
much simpler to add new DAOs and extend them with custom methods. No action needs
to be taken to support “out of the box” data access functionality for any persistent
business object. For example, to have full DAO support for a Category object, you’d
simply create a new GenericDao<Category> instance.

But there are times when you’ll need to add additional capabilities to the default DAO
behavior; such as adding a custom DAO method. Look at
Northwind.Core/ISupplierDao.cs to see the interface of a custom DAO for doing just
that. The implementation of this custom DAO is Northwind.Data/SupplierDao.cs. These
classes simply inherit from IDao<Supplier> and GenericDao<Supplier>, respectively,
to include the “out of the box” DAO functionality with the new, custom DAO method.

In the incredibly rare circumstance wherein your object requires an assigned ID, then
instead inherit from GenericDaoWithTypedId. Look at
Northwind.Core/ICustomerDao.cs as an example of this. The implementation of the
custom DAO class is Northwind.Data/CustomerDao.cs. Notice that this class inherits
from GenericDaoWithTypedId<Customer, string> because Customer has an ID type
other than int. This particular DAO was included to demonstrate an example of
supporting an object with an assigned ID. (Please note that assigned IDs are the spawn of
the devil and should be avoided.)
Northwind.Tests: The Unit Testing Layer
This class library contains all of the unit tests for testing the layers of your custom
application. Browse these tests to see examples of how the various other layers are
tested.

Northwind.Web: The “V” in MVC
This is the web layer of the sample application which ties everything together via
configuration and exposes the presentation pages.

Hosting WCF Services via IIS
In addition to views, this layer contains an example of hosting a WCF service via IIS.
Furthermore, Ninject is leveraged to facilitate dependency injection of a DAO to the
underlying service class. A key to hosting WCF services side by side with ASP.NET
MVC is to inform the application that WCF services should not be handled by the MVC
routing engine. Accordingly, the following line within Global.asax.cs decouples the
WCF services from MVC processing:

routes.IgnoreRoute("{resource}.svc");

Examining the Reusable Class Libraries
SharpArch.Core
Contains basic utilities, e.g., a Design by Contract class, and persistence agnostic data
access support.

Of particular note:
    /PersistenceSupport/IDao.cs: Provides a base DAO interface to be used by all
        DAO objects.
    /PersistenceSupport/PersistentObject.cs: Acts as a base class for all entity classes.
        This class provides functionality including an ID property and a standardized
        means of performing object comparisions with Equals.
    DesignByContract.cs: A design-by-contract (DbC) utility originally written by
        Kevin McFarlane and described in detail at
        http://www.codeproject.com/KB/cs/designbycontract.aspx. The modified version
        included within S#arp Architecture does not support turning off DbC enforcement
        with compile time flags.

Further details of the provided objects may be found in the comments of each item.

SharpArch.Data
Provides “out of the box” data access functionality using NHibernate.

Of particular note:
    /NHibernate/DaoTests.cs: Provides a base class for unit tests which act upon a
        live database. A transaction is begun before each test and is then rolled back upon
        completion of the test, regardless of success or failure. Consequently, database
        changes made within a unit test will not have a permanent effect on the persisted
        data.
       /NHibernate/GenericDao.cs: The “out of the box” data access object that may be
        used directly, with a generic qualifier, or as a base class for all concrete DAOs.
       /NHibernate/NHibernateSession.cs: Provides a means for getting an NHibernate
        session. It also builds the NHibernate session factory upon creation.

SharpArch.Web
Includes classes for supporting use of SharpArch within an ASP.NET MVC context.

Of particular note:
    /NHibernate/TransactionAttribute.cs: An ActionFilterAttribute for wrapping
        MVC actions within a transaction.
    /NHibernate/WesSessionStorage.cs: An ISessionStorage implementation for
        storing the NHibernate session in a web context. (This is not specific to MVC
        and may be leveraged in a classic ASP.NET environment.)
    /Ninject/ControllersAutoBindModule.cs: Automatically binds controllers to the
        Ninject kernel to support dependency injection. I.e., eliminates the need to
        manually register each and every controller within a Ninject module.

Developing with the Base Architecture Exercise
The following example details all steps for creating a new domain object listing form. It
covers creating the domain objects, creating and testing the controller with mock objects,
extending data access objects with a custom method, configuring DAOs for dependency
injection and displaying the results on a web page.

Test Driven Development Cycle
The following test-driven cycle will be used:
   1)   Write your test as if the target objects and API already exists.
   2)   Compile the solution and see it break.
   3)   Write just enough code to get it to compile.
   4)   Run the test and see if fail.
   5)   Write just enough code to get it to pass.
   6)   Run the test and see it pass!
   7)   Refactor if necessary!

For the purposes of this example, the user story is as follows: Users may search for staff
members matching a name filter. The results should include any staff members with a
first name, last name, or employee number containing the provided filter.

Assume that we haven’t yet tackled another user story defined as “User may create staff
member having a unique employee number” yet; so although not necessary yet, because
it’s not dictated in the current user story that we’re tackling, let’s keep in mind that the
staff member’s employee number is what makes it unique. With that said, let’s start with
the domain model to support the staff member.
Developing the Staff Member Domain Model
  1) Go to Northwind.Tests/Northwind.Core and add a new tests class called
     StaffMemberTests.cs. with an initial test of CanCreateStaffMember(). (Note that the test
     is written as a question.) The class should look as follows:

      using NUnit.Framework;
      using NUnit.Framework.SyntaxHelpers;
      using Northwind.Core;

      namespace Tests.Northwind.Core
      {
          [TestFixture]
          public class StaffMemberTests
          {
              [Test]
              public void CanCreateStaffMember() {
                  string employeeNumber = "ABC123";
                  string firstName = "Karel";
                  string lastName = "Čapek";

                      StaffMember staffMember =
                          new StaffMember(employeeNumber) {
                              FirstName = firstName,
                              LastName = lastName
                          };

                      Assert.That(staffMember.EmployeeNumber,
                          Is.EqualTo(employeeNumber));
                      Assert.That(staffMember.FirstName,
                          Is.EqualTo(firstName));
                      Assert.That(staffMember.LastName,
                          Is.EqualTo(lastName));
                }
           }
      }



      There are a couple of things to note in the above test:
          The constructor of StaffMember only takes an employee number. This is the
              minimal amount of information to create a valid, unique staff member, as
              specified by the requirements.
          The first assert compares the staff member to a new staff member with the same
              employee number. Since the employee number is what makes staff members
              unique, then this should pass without worrying about the first and last names.
          The next two asserts make sure the first and last names match as well.

  2) Compile the build and notice that it breaks due to the missing StaffMember class.

  3) Go to Northwind.Core and add a StaffMember.cs class file to develop the StaffMember
     domain object, as follows: (Note that we’ve only added just enough code to get the test
     to compile.)
    namespace Northwind.Core
    {
        public class StaffMember
        {
            public StaffMember(string employeeNumber) {}

               public string EmployeeNumber { get; set; }
               public string FirstName { get; set; }
               public string LastName { get; set; }
         }
     }



4) Open NUnit and load the tests project by going to File / Open Project and open
   Northwind.Tests/bin/Debug/Northwind.Tests.dll. Double click the
   CanCreateStaffMember test to have it run. You should see it fail because
   EmployeeNumber is null.

5) Go back to the StaffMember domain object and alter the constructor as follows:

    public StaffMember(string employeeNumber) {
        EmployeeNumber = employeeNumber;
    }

6) Compile and run the test and again to see it go green…woohoo!

7) Time to refactor! In the constructor of StaffMember, it’s possible to set the
   employeeNumber parameter to a null or empty string object. This is bad. What we’d
   like to do is enforce that a valid employee number is provided. Let’s use the design-by-
   contract utility to enforce this with a Check.Require. This is good. Furthermore, to
   protect the employee number in the future, since it shouldn’t change, let’s protect the
   setter of EmployeeNumber. Be sure to run the unit tests again to make sure nothing
   broke while refactoring.

    When implementing this refactoring, a test driven approach should be followed, as was
    performed in the previous six steps. For brevity, the unit test below demonstrates step
    one of the refactoring process followed by code which gets the test to pass in step six of
    the process. (Note that we can’t unit test proving that the EmployeeNumber’s setter is
    protected as it will not compile if we attempt to set it.)

    using SharpArch.Core;

    [Test]
    [ExpectedException(typeof(PreconditionException))]
    public void CannotCreateStaffMemberWithInvalidEmployeeId() {
        new StaffMember(" ");
    }

    using SharpArch.Core;
    using SharpArch.Core.PersistenceSupport;
       using System;

       namespace Northwind.Core
       {
           public class StaffMember
           {
               public StaffMember(string employeeNumber) {
                   Check.Require(!string.IsNullOrEmpty(employeeNumber)
                       && employeeNumber.Trim() != String.Empty,
                       "employeeNumber must be provided");

                      EmployeeNumber = employeeNumber;
                 }

                 public string EmployeeNumber { get; protected set; }
                 public string FirstName { get; set; }
                 public string LastName { get; set; }
            }
       }


Enabling the Domain for Comparisons and Persistence
So now we have our basic domain model in place to support creating staff members from
a domain perspective. Within the requirements, as was discussed, the employee number
is the basis for staff member uniqueness; therefore, we’ll want to be able to compare staff
members for equality for this field. Here’s where we begin leveraging the S#arp
Architecture framework to support comparisons and, as a side effect, to prep our domain
object for database storage and retrieval.

   1) Within StaffMemberTests.cs, add a new test called CanCompareStaffMembers().The
      method should look as follows:

       [Test]
       public void CanCompareStaffMembers() {
           string employeeNumber = "ABC123";

            StaffMember staffMember = new StaffMember(employeeNumber);

            Assert.That(staffMember, Is.EqualTo(
                new StaffMember(employeeNumber)));
       }

   2) Compile the build; it’ll compile because objects are always comparable. So we’ve also
      taken care of the write-just-enough-code-to-get-it-to-compile step.

   3) Within NUnit, double click the CanCompareStaffMembers test to have it run. It will fail
      because the comparison is using the “out of the box” Equals() method.

   4) To enable consistent comparisons of domain objects, alter StaffMember to inherit from
      PersistentObject, and add a DomainSignature attribute above the property(s) which
      makes the staff member unique, as follows:
public class StaffMember : PersistentObject
{
    ...

     [DomainSignature]
     public string EmployeeNumber { get; protected set; }
}

Inheriting from PersistentObject and adding the attribute has had a few effects on the
StaffMember object:
     By default, PersistentObject assumes that the object has an ID of type int;
         consequently, StaffMember now has an ID property of type int with a public
         getter and protected setter. (Due to a variety of drawbacks, only the hydration
         mechanism, e.g., Nhibernate, should be able to set this ID property.) If you need
         an ID having a type other than ID, inherit instead from
         PersistenObjectWithTypedId<IdType>. And if you really need to set the ID
         property manually, implement the IHasAssignedId interface.
     Equals() and GetHashCode() have been provided by default for consistent
         behavior. Most of the details behind this may be found at
         http://devlicio.us/blogs/billy_mccafferty/archive/2007/04/25/using-equals-
         gethashcode-effectively.aspx. There is a crucial difference between the current
         architecture and what was described in this blog post: GetHashCode() has been
         moved up to PersistentObject so only the “domain signature” has to be defined
         via the addition of attributes. Furthermore, the comparison behavior has been
         abstracted into a DomainSignatureComparable class so as to serve as an optional
         base class for non-persistent objects. To read more about the importance of
         providing Equals and GetHashCode for NHibernate, see
         http://www.hibernate.org/hib_docs/nhibernate/html/persistent-
         classes.html#persistent-classes-equalshashcode.

        Behind the scenes, the “domain signature” gets automatically created by
        performing bitwise XORs between all the domain signature properties resulting
        in an int HashCode defining what makes an object unique. Alternatively, you
        can forego using attributes and define the domain signature yourself by
        overriding GetDomainSignature(). For example, if the first and last names were
        the defining fields for uniqueness, the contents of your overridden
        GetDomainObjectSignature() could instead reflect the following:

        return FirstName.GetHashCode() ^ LastName.GetHashCode();

        To reiterate the easier alternative, you could simply add the [DomainSignature]
        attribute above both the FirstName and LastName properties which has the same
        behavior as the example above.

        So what if the domain signature happens to include another PersistentObject (or
        other reference type) as part of its domain signature? For example, assume that
                the FirstName, LastName and HomeAddress are what make the StaffMember
                unique. The contents of GetDomainObjectSignature(), which assumes the strings
                will never be null, could then reflect:

                return FirstName.GetHashCode() ^ LastName.GetHashCode() ^
                  (HomeAddress != null ? HomeAddress.GetHashCode() : 0);

                The following illustrative example (i.e., don’t modify the tutorial code you’re
                working on to reflect this) shows an example of creating a multi-part signature
                using the DomainSignature across multiple properties. It’s alright if the
                properties which make up an object’s domain signature are value or reference
                types; the base class will check for nulls.

       using SharpArch.Core;
       using SharpArch.Core.PersistenceSupport;
       using System;

       namespace Northwind.Core
       {
           public class StaffMember
           {
               ...

                  [DomainSignature]
                  public string FirstName { get; set; }

                  [DomainSignature]
                  public string LastName { get; set; }

                  [DomainSignature]
                  public Address HomeAddress { get; set; }

                  // An override of GetDomainObjectSignature
                  // is not necessary with this approach
            }
       }


    5) Compile and run the test and again to see it go green…gotta love the green!

Developing the Controller to Retrieve and Display Results
We now have the basics in place for our domain model. We have two options to proceed, we can
develop the controller or we can build the mechanism to retrieve results from the database. As a
general rule, there are two things that we want to delay as long as possible: writing any
presentation pages and writing any data access code against a live database. Delaying these keeps
our attention focused on the domain and the interactions with the behavior of the domain.
Therefore, let’s proceed with developing the controller and we’ll fake our interactions with a live
database.
    1) As always, let’s start with a unit test…surprised? Under
        Northwind.Tests/Northwind.Controllers, add a new class called
StaffMembersControllerTests which contains a single test. An explanation of what is
happening follows the code.

using   NUnit.Framework;
using   Northwind.Core;
using   MvcContrib.TestHelper;
using   SharpArch.Core.PersistenceSupport;
using   Rhino.Mocks;
using   System.Collections.Generic;
using   NUnit.Framework.SyntaxHelpers;
using   Northwind.Controllers;
using   Northwind.Core.DataInterfaces;
using   System.Web.Mvc;

namespace Tests.Northwind.Controllers
{
    [TestFixture]
    public class StaffMembersControllerTests
    {
        [SetUp]
        public void Setup() {
            testControllerBuilder = new TestControllerBuilder();
        }

          [Test]
          public void CanListFilteredStaffMembers() {
              StaffMembersController controller =
                  new StaffMembersController(
                      CreateMockStaffMemberDao());

               testControllerBuilder
                   .InitializeController(controller);

               ViewResult result =
                   controller.ListStaffMembersMatching("martin")
                       .AssertViewRendered()
                       .ForView("ListStaffMembersMatchingFilter");

               Assert.That(result.ViewData, Is.Not.Null);
               Assert.That(result.ViewData.Model as
                   List<StaffMember>, Is.Not.Null);
               Assert.That((result.ViewData.Model as
                   List<StaffMember>).Count, Is.EqualTo(4));
          }

          /// <summary>
          /// In most cases, we'd simply return
          /// IDao<MyPersistentObject>, but since we're
          /// leveraging a custom DAO method, we need a
          /// custom DAO interface.
          /// </summary>
          public IStaffMemberDao CreateMockStaffMemberDao() {
              MockRepository mocks = new MockRepository();

               IStaffMemberDao mockedDao =
                   mocks.CreateMock<IStaffMemberDao>();
                 Expect.Call(mockedDao.LoadAllMatching(null))
                     .IgnoreArguments()
                     .Return(CreateStaffMembers());
                 mocks.Replay(mockedDao);

                 return mockedDao;
           }

           private List<StaffMember> CreateStaffMembers() {
               List<StaffMember> staffMembers =
                   new List<StaffMember>();

                 staffMembers.Add(new         StaffMember("ABC123"));
                 staffMembers.Add(new         StaffMember("DEF456"));
                 staffMembers.Add(new         StaffMember("GHI789"));
                 staffMembers.Add(new         StaffMember("Abracadabera"));

                 return staffMembers;
           }

           private TestControllerBuilder testControllerBuilder;
     }
}

That’s quite a mouthful! Here’s what the code is trying to verify… It’s making sure that
if we call the controller’s ListStaffMembersMatching() method, then the controller will
invoke the IStaffMemberDao.LoadAllMatching() method to retrieve the results and put
them into the ViewData.

(In order to facilitate more useful testing functionality of the controller, such as
simulating an HTTP form submission, the controller should to be initialized using the
TestControllerBuilder from the MvcContrib project.)

Notice that the constructor of the controller accepts the return value from
CreateMockStaffMemberDao(), which is a concrete instance of IStaffMemberDao. This
doesn’t exist yet, but we know that the controller is going to need it…this is the first D in
TDD. By passing IStaffMemberDao into the constructor of the controller, we’re
performing “manual dependency injection,” enabling ourselves to unit test the controller
without a live database. For more information on dependency injection, read
http://www.codeproject.com/KB/architecture/DependencyInjection.aspx - the “mock”
objects in this article are actually “stubs”…but I digress.

The CreateMockStaffMemberDao() method itself is an example of creating a true mock
object, using an external library called Rhino Mocks
(http://www.ayende.com/projects/rhino-mocks.aspx). This mock object simulates
interaction with a live database. In this way, we’ve foregone digging into the data access
layer until we have the business logic completely pinned down...no, it’s not because
we’re hopeless procrastinators putting off all the tedious work until the interns start, we
simply want to be able to focus on the domain logic until the details are worked out. For
   more information on mocking the database (no pun intended), see
   http://www.martinfowler.com/articles/mocksArentStubs.html.

2) Compile the solution and see the compilation break. It’ll complain because both
   StaffMembersController and IStaffMemberDao don’t yet exist.

3) To get the code to compile, create IStaffMemberDao first since the controller depends on
   it. To do so, go to Northwind.Core/DataInterfaces and add a new interface called
   IStaffMemberDao, as follows:

   using SharpArch.Core.PersistenceSupport;
   using System.Collections.Generic;
   using Northwind.Core;

   namespace Northwind.Core.DataInterfaces
   {
       public interface IStaffMemberDao : IDao<StaffMember >
       {
           List<StaffMember> LoadAllMatching(string filter);
       }
   }



   This inherits from IDao<StaffMember > which resides in SharpArch.Core. This general-
   use DAO interface declares a number of standard DAO methods such methods as
   LoadAll() and Delete(). All that needs to be done for now is to extend it with one
   additional method, LoadAllMatching().

   When using S#arp Architecture, IDao<MyObject> should be used as the basis for all
   custom DAOs without exception. If your object has an ID type other than int, then
   implement IDaoWithTypedId<MyObject, IdType>, instead.

   The key point is that the Northwind.Core assembly does not contain any data access
   implementation details; it only declares, and has access to, data access interfaces. As
   discussed later on, the concrete DAO, containing the implementation details, will be
   added to Northwind.Data (but not until we need it). Having the interface separated from
   the implementation details located in a different assembly is known, appropriately
   enough, as “Separated Interface”
   (http://www.martinfowler.com/eaaCatalog/separatedInterface.html). (Uncle Bob, aka
   Robert Martin, originally coined this technique as “Dependency Inversion.”)

   Getting back to the task at hand, go to Northwind.Controllers and add a
   StaffMembersController class; it should have just enough code to compile:

   using   Northwind.Core;
   using   System.Collections.Generic;
   using   Northwind.Core.DataInterfaces;
   using   System.Web.Mvc;
    using SharpArch.Web;

    namespace Northwind.Controllers
    {
        public class StaffMembersController : Controller
        {
            public StaffMembersController(
                IStaffMemberDao staffMemberDao) {}

               public ActionResult ListStaffMembersMatching(
                   string filter) {
                   return null;
               }
         }
    }



4) Build the solution, head back to NUnit, run the CanListFilteredStaffMembers test, and
   see it fail it a fit of agonizing pain. So of a!!! (But wait, that’s exactly what we want to
   see at this point.)

5) We now simply have to add a couple lines of code to the controller to get the unit test to
   pass:

    using    Northwind.Core;
    using    System.Collections.Generic;
    using    Northwind.Core.DataInterfaces;
    using    System.Web.Mvc;
    using    SharpArch.Core;
    using    SharpArch.Web;

    namespace Northwind.Controllers
    {
        public class StaffMembersController : Controller
        {
            public StaffMembersController(
                IStaffMemberDao staffMemberDao) {
                Check.Require(staffMemberDao != null,
                    "staffMemberDao may not be null");

                     this.staffMemberDao = staffMemberDao;
               }

               public ActionResult ListStaffMembersMatching(
                   string filter) {
                   List<StaffMember> matchingStaffMembers =
                       staffMemberDao.LoadAllMatching(filter);

                     return View("ListStaffMembersMatchingFilter",
                         matchingStaffMembers);
               }

               private readonly IStaffMemberDao staffMemberDao;
         }
       }



       Arguably, adding the Check.Require within the constructor is a little more than “just
       enough” code to get the test to pass. But with that said, adding Check.Require statements
       all over the place should become habitual while coding. It only takes a moment to write
       and will end up saving you hours in the debugger. And if you’re worried about these
       checks causing a performance hit, there are far larger fish to fry than these.

   6) Now run the NUnit test again and you should be seeing green. We were able to do all of
      this without yet defining our staff members table in the database. But we’re not going to
      get much further without doing that bit as well…

Retrieving Results via a Custom DAO
As requested, the requirements of this tutorial stipulate that the user may provide a filter
to retrieve staff members matching their first name, last name, and/or employee number.
Up to this point, we’ve been able to ignore the persistence layer, but will need to address
it now.
   1) Go to Northwind.Tests/Northwind.Data and add a new class called
      StaffMemberDaoTests; this will contain a single test to prove that our custom DAO
      method is working as expected:

       using    NUnit.Framework;
       using    Northwind.Core;
       using    Northwind.Core.DataInterfaces;
       using    System.Collections.Generic;
       using    NUnit.Framework.SyntaxHelpers;
       using    SharpArch.Data.NHibernate;
       using    Northwind.Data;

       namespace Tests.Northwind.Data
       {
           [TestFixture]
           [Category("DB Tests")]
           public class StaffMemberDaoTests : DaoTests
           {
               [Test]
               public void CanLoadStaffMembersMatchingFilter() {
                   List<StaffMember> matchingStaffMembers =
                       staffMemberDao.LoadAllMatching("TEST_FiLtEr");

                       Assert.That(matchingStaffMembers.Count,
                           Is.EqualTo(3));
                  }

                  private IStaffMemberDao staffMemberDao =
                      new StaffMemberDao();
            }
       }

       The benefit of inheriting from DaoTests is twofold: during setup, the NHibernate session
    factory is initialized and a transaction is opened; during teardown, at the end of each test,
    the transaction is rolled back. In this way, the database is left unmodified after all the
    tests have run.

    Notice that at the top of the test class, an attribute has been included to indicate that this
    test is within the “DB Tests” category. Categorizing this test enables you to disable the
    running of these unit tests within NUnit. Why would you want to do that? Because unit
    tests which connect to a database are painfully slow, taking a few seconds to load and
    run. This doesn’t sound too bad until you have dozens or hundreds of DB tests to run.
    This can turn into minutes of test running time. If all the tests take more than a few
    seconds to run, then developers stop running them. And once developers stop running
    them, tests start breaking and the quality of the code degrades. So by turning the DB
    tests off while running the domain logic tests allows a developer to run all of the fast tests
    very often and run the time consuming tests when appropriate. The continuous
    integration server will also be running all of the longer running tests every time a change
    is checked in, so they’ll get checked sooner rather than later anyway…assuming you’re a
    good coder who checks in changes frequently!

    Note, in the unit test, that we’re asserting that we expect three matching staff members.
    We’ll have to create our test data in the database, accordingly.

2) Since we’ve already created IStaffMemberDao, but haven’t created the StaffMemberDao
   concrete implementation, this unit test will not compile. At this point, add a
   StaffMemberDao class to Northwind.Data and have it inherit from
   GenericDao<StaffMember> and implement IStaffMemberDao. To get the solution to
   compile, you’ll need to also implement the LoadAllMatching method from
   IStaffMemberDao, but just throw a NotImplementedException within it.

3) Running the CanLoadStaffMembersMatchingFilter test in NUnit fails, as it should. It
   will complain – unsurprisingly enough – that a NotImplentedException was thrown. So
   let’s start there first…

4) In writing just enough code to get this test to pass, we’re going to have to do a few tasks
   to get the data access plumbing in place:

        a. Create the DAO which implements IStaffMemberDao. This class will contain the
           implementation details of the custom DAO method that we added to the base
           IDao interface within IStaffMemberDao. As was done in the previous step, a
           new class, called StaffMemberDao was added to Northwind.Data which
           implements IStaffMemberDao. Use the following to build out the remaining
           details of this class:

            using Northwind.Core.DataInterfaces;
            using Northwind.Core;
            using System.Collections.Generic;
using NHibernate;
using SharpArch.Data.NHibernate;
using NHibernate.Criterion;

namespace Northwind.Data
{
    public class StaffMemberDao :
        GenericDao<StaffMember>, IStaffMemberDao
    {
        public List<StaffMember> LoadAllMatching(
            string filter) {
            ICriteria criteria =
                Session.CreateCriteria(typeof(StaffMember))
                .Add(
                    Expression.Or(
                         Expression.InsensitiveLike(
                             "EmployeeNumber",
                             filter,
                             MatchMode.Anywhere),
                         Expression.Or(
                             Expression.InsensitiveLike(
                                 "FirstName",
                                 filter,
                                 MatchMode.Anywhere),
                             Expression.InsensitiveLike(
                                 "LastName",
                                 filter,
                                 MatchMode.Anywhere))))
                .AddOrder(
                    new NHibernate.Criterion.Order(
                         "LastName", true));

               return criteria.List<StaffMember>()
                   as List<StaffMember>;
          }
     }
}

The above code implements/inherits from two objects: IStaffMemberDao which
we’ve already seen, and GenericDao<StaffMember> which comes from
SharpArch.Data.NHibernateSupport. The GenericDao base class implements
IDao and provides most of the basic DAO CRUD functionality that we’ll ever
need. The benefit to inheriting from this base implementation in our custom
DAO is that we only need to provide details for our custom method,
LoadAllMatching(string filter). Writing a custom DAO is usually the
exception than the norm; more often than not, GenericDao will provide all
the DAO functionality we need.

In the example code, the querying mechanism uses Hibernate Query Language
(HQL); for more information about using HQL, see the NHibernate reference
documentation at
http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html. My only
    complaint with HQL is that string literals are used instead of strongly typed
    references; a few good solutions exist to solve this complaint:
         LINQ to NHibernate (which isn’t compatible with NHibernate 2.0 as of
            the 0.8 release of S#arp Architecture):
            http://www.hookedonlinq.com/LINQToNHibernate.ashx
         NHibernate Query Generator:
            http://www.ayende.com/Blog/archive/7186.aspx
         Strongly Typed Criteria:
            http://bugsquash.blogspot.com/2008/03/strongly-typed-nhibernate-
            criteria-with.html

    An additional issue in this project is that the name “Order” occurs in both
    Northwind.Core (as a domain object) and NHibernate.Expression (as a method).
    Therefore, we must spell out the use of NHibernate.Expression.Order to avoid
    ambiguity.

b. Alter the domain object to have virtual properties and a no-argument
   constructor. When NHibernate loads objects, it does so “lazily” by default. This
   means that if a request is made to load an object, NHibernate actually returns a
   proxy to the object. Only when the object is used in some way is an actual trip to
   the database made. This behavior can be modified on a case by case basis and
   will improve performance in some cases. To facilitate StaffMember objects
   being lazily loaded by NHibernate, its class properties and methods need to be
   defined as virtual. So under Northwind.Core, modify StaffMember.cs as follows:

    public virtual string EmployeeNumber { get; protected set;}
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }

    If you didn’t do this, NHibernate would complain that the properties need to be
    defined as virtual to work with the default, lazy behavior. To learn more about
    the proxy design pattern in general, see
    http://www.dofactory.com/Patterns/PatternProxy.aspx.

    In addition to needing virtual properties and methods to lazily load an object,
    NHibernate also requires that the domain object have a no-argument constructor
    in order to create and hydrate the object with data from the database. As we do
    not want anyone creating a StaffMember object without supplying an employee
    number, we can simply add a protected no-argument constructor, as in the first
    line below:

    protected StaffMember() { }

    public StaffMember(string employeeNumber) {
        Check.Require(!string.IsNullOrEmpty(employeeNumber) &&
            employeeNumber.Trim() != String.Empty,
               "employeeNumber must be provided");

         EmployeeNumber = employeeNumber;
    }

    In this way, our domain logic is enforced while facilitating NHibernate to load
    the object.

c. Create the NHibernate mapping file (HBM). This XML configuration file
   informs NHibernate how to translate the StaffMember object into a row in the
   database and vice versa. To do so, go to Northwind.Core and add a new XML
   file called StaffMember.hbm.xml. (The “hbm” in the name is crucial.)
   Immediately after adding the file, right click it and bring up its properties;
   set the “Build Action” to “Embedded Resource.” Missing this step is
   probably the most common NHibernate mistake a developer makes; seeing an
   error of “unknown entity” is a good indication that this file has not been set to be
   an embedded resource. Setting it as an embedded resource embeds the XML file
   directly into the compiled DLL so that they do not have to be explicitly deployed
   to the deployment server. The StaffMember.hbm.xml should reflect the
   following:

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                       assembly="Northwind.Core"
                       namespace="Northwind.Core">
          <class name="StaffMember" table="StaffMembers">
                <id name="ID" column="StaffMemberId"
                      unsaved-value="0">
                      <generator class="identity" />
                </id>

                <property name="EmployeeNumber"
                          column="EmployeeNumber" />
                <property name="FirstName"
                          column="FirstName" />
                <property name="LastName"
                          column="LastName" />
          </class>
    </hibernate-mapping>



    This HBM is everything that is needed to inform NHibernate how to perform
    CRUD operations on a StaffMember object using the StaffMembers table. What
    StaffMembers table you ask? We’ll get to that next.

    Logically, the HBM file is data-specific and belongs in Northwind.Data. It has
    everything to do with the data persistence mechanism and isn’t needed to support
    a domain driven design. There’s one specific reason that I put HBMs in the
    Northwind.Core assembly right next to the domain objects that they describe:
    convenience! Whenever I alter StaffMember.cs, it’s trivially simple for me to
    open up the describing HBM, sitting right next to it, to modify it accordingly. If
    it were sitting in Northwind.Data, I’d have to search around in another class
    library to look for where it is. I can justify keeping it in Northwind.Core because
    it requires no physical references to be added to Northwind.Core for resources
    such as System.Data or NHibernate. The HBMs are simply along for the ride in
    Northwind.Core, quickly available to me whenever the domain gets altered.

d. Create the table to support the HBM. Many developers start with a database
   model and allow it to be the driving factor in designing the application. This is
   an aspect of model driven design. The ADO.NET Entity Framework is a perfect
   example of a solid model driven design framework. The approach that many
   espouse is domain driven design wherein the database becomes an afterthought
   to support the domain model. For more information on domain driven design,
   see http://www.infoq.com/minibooks/domain-driven-design-quickly which is a
   concise summary of Eric Evans’ classic book, Domain Driven Design. To add
   the table, run the following within the Northwind database (which was generated
   with SQL Server 2005):

    USE Northwind
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    SET ANSI_PADDING ON
    GO
    CREATE TABLE [dbo].[StaffMembers](
           [StaffMemberId] [int] IDENTITY(1,1) NOT NULL,
           [EmployeeNumber] [varchar](50) NOT NULL,
           [FirstName] [varchar](50) NOT NULL CONSTRAINT
    [DF_StaffMembers_FirstName] DEFAULT (''),
           [LastName] [varchar](50) NOT NULL CONSTRAINT
    [DF_StaffMembers_LastName] DEFAULT (''),
      CONSTRAINT [PK_StaffMembers] PRIMARY KEY CLUSTERED
    (
           [StaffMemberId] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
    IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
    ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO
    SET ANSI_PADDING OFF



e. Populate the table with test data to support passing the test. Before inserting the
   test data, it should be noted that attention should be put towards how a test
   database will be managed. If the test data gets out of synch with the tests, then
   the tests start breaking. And once they start breaking, and aren’t fixed quickly,
               then people stop running them. So any test that depends on live data in a
               database should be considered a fragile test and avoided unless absolutely
               necessary. Due to the complexity of our query, this is one of those cases.

               USE Northwind
               GO

               INSERT INTO StaffMembers
               VALUES ('thistest_Filter', 'Mike', 'Park')

               INSERT INTO StaffMembers
               VALUES ('ABC123', '_test_FiLtEr_', 'Vance')

               INSERT INTO StaffMembers
               VALUES ('GHI789', 'Lynette', 'Knackstedt')

               INSERT INTO StaffMembers
               VALUES ('DEF456', 'Gerry', 'Lundquistest_filtER')

               With the above data in place, the “TEST_FiLtEr” filter in the unit test should
               match all but the third entry when we run it.

   5) Now run the CanLoadStaffMembersMatchingFilter and see it pass! The test successfully
      connected to the database, ran the provided filtering query, loaded the objects with
      NHibernate’s help, and returned the results to the unit test as a strongly typed listing of
      StaffMember objects. No datasets…no ADO.NET…no connection management…no
      stored procedures…no thousands of lines of auto-generated data access code!

   6) There’s nothing to refactor at this point, but a five minute break is certainly warranted!

Showing the Results in a View
The domain’s been created, the data access mechanism exists, the controller has been
developed...the only thing remaining is a little HTML to pull it altogether. By the time
you get here, the view is but a minor afterthought.
There are a variety of opinions on how much of the view layer should be unit tested. On
one hand, the view layer changes so frequently that a lot of maintenance is required to
manage tightly coupled view-oriented unit tests via a tool such as NUnitAsp
(http://nunitasp.sourceforge.net) or Selenium (http://selenium.openqa.org). On the other
hand, it’s not a bad idea to create web “smoke tests” to at least make sure the stated URL
isn’t blatantly breaking. For an example of a web smoke test, see
http://geekswithblogs.net/Billy/archive/2006/05/10/77820.aspx.

For this example, we’ll get right to the heart of the matter and create the view:

   1) Go to Northwind.Web/Views and add a new directory called StaffMembers. The name
      of this folder needs to be the first part of the name of the StaffMembersController
      controller class that it is associated with; consequently, it’s very important that it’s named
      this way.
2) Under the StaffMembers directory, add a new MVC View Content Page called
   ListStaffMembersMatchingFilter.aspx and select Site.Master (in /Views/Shared) as the
   master page. The ASPX should be modified to reflect the following:

   <%@ Page Title="" Language="C#"
       MasterPageFile="~/Views/Shared/Site.Master"
       AutoEventWireup="true"
       CodeBehind="ListStaffMembersMatchingFilter.aspx.cs"
   Inherits="Northwind.Web.Views.StaffMembers.ListStaffMembersMatchi
   ngFilter" %>
   <%@ Import Namespace="Northwind.Core" %>

   <asp:Content ID="Content1"
                 ContentPlaceHolderID="MainContentPlaceHolder"
                 runat="server">
       <p>Matching Staff Members:</p>
       <asp:ListView ID="staffMemberList" runat="server">
          <LayoutTemplate>
            <ul>
               <asp:PlaceHolder ID="itemPlaceHolder" runat="server"
   />
            </ul>
          </LayoutTemplate>
          <ItemTemplate>
            <li>
            <%# ((StaffMember) Container.DataItem).EmployeeNumber %>
            </li>
          </ItemTemplate>
       </asp:ListView>
   </asp:Content>

   The corresponding code-behind should then look as follows:

   using System.Web.Mvc;
   using Northwind.Core;
   using System.Collections.Generic;

   namespace Northwind.Web.Views.StaffMembers
   {
       public partial class ListStaffMembersMatchingFilter :
           ViewPage<IEnumerable<StaffMember>>
       {
           public void Page_Load() {
               staffMemberList.DataSource = ViewData.Model;
               staffMemberList.DataBind();
           }
       }
   }



   The code-behind could have inherited from ViewPage<List<StaffMember>>, but
   inheriting from ViewPage<IEnumerable<StaffMember>> makes it much more flexible
       and reusable by a variety of controllers which may not always have a List<StaffMember>
       available.

   3) Configure the Ninject module to let the controller factory know how to inject the
      IStaffMemberDao dependency into the controller. Accordingly, go to
      Northwind.Web/NinjectModules/DataModule.cs and alter the code to reflect the
      following:

       using   Ninject.Core;
       using   SharpArch.Core.PersistenceSupport;
       using   Northwind.Core;
       using   SharpArch.Data.NHibernate;
       using   Northwind.Core.DataInterfaces;
       using   Northwind.Data;

       namespace Northwind.Web.NinjectModules
       {
           public class DataModule : StandardModule
           {
               public override void Load() {
                   Bind<IDao<Category>>().To<GenericDao<Category>>();
                   Bind<ICustomerDao>().To<CustomerDao>();
                   Bind<IStaffMemberDao>().To<StaffMemberDao>();
               }
           }
       }

       The load method informs the controller factory that whenever it creates a controller
       which requires an IStaffMemberDao as a constructor parameter, it should inject an
       instance of StaffMemberDao. While the latter two bindings demonstrate binding a
       custom DAO, the first shows what needs to be done for each “out of the box” DAO that
       you will be leveraging.

   4) Give it a whirl! Hit F5 and change the URL to reflect
      http://localhost:1660/StaffMembers.mvc/ListStaffMembersMatching?filter=test_Filter.
      You should be presented with the same three users that your unit test returned from the
      database.

What Was Accomplished?
The above steps have taken us through a test driven approach of designing a domain
model, creating a controller which uses a custom DAO, testing with a mock database,
interacting with a live database, and displaying results in an MVC view. There’s plenty
more to learn, but this covers the basics.

S#arp Architecture Best Practices
All of the best practices described below should be seen as general rules of thumb which
are certainly subject to excepted cases. But any exception to the rule should have a
justifiable reason, accordingly.
Within the Web Layer
When using ASPX views
      Within a data bound control, avoid using Eval(“PropertyName”). Instead, convert
       the data item to a domain object to leverage strongly typed accessors; e.g.:
       <%# ((Customer) Container.DataItem).ContactName %>

Configuring web.config
      In production environments, include the following setting:
       <compilation debug=”false” />
      Disable session state by default:
       <sessionState mode=”Off” />
      Disable view state by default:
       <pages enableViewState=”false” />
       If you find that you absolutely have to have it on a particular page or control,
       enable it on the page or control only:
       For pages: <%@ Page EnableViewState=”True” %>
       For controls: <asp:ControlType enableViewState=”true”>
      Declare customer server controls in web.config:
       <pages>
         <controls>
           <add tagPrefix=”MyPrefix”
                namespace=”MyNamespace” assembly=”MyAssembly” />
         </controls>
       </pages>


Managing Ninject Modules
While it’s best to avoid putting any “pure” code classes into the web layer, I feel it most
appropriate to place the Ninject module classes within MyProject.Web/NinjectModules.
As a rule, there should be one module class for each class library that it supports, using
the class libraries scope as part of the module name; e.g., DataModule, CoreModule,
WcfModule, etc.

Within the Controllers Layer
When passing data from a controller to a view, Data Transfer Objects (DTOs) should be
used to encapsulate multiple data elements to be strongly type passed to a view. For
example, assume you have a ProductsController with an action called List. The view
data DTO, if it contains more than one type of object, would be called ListViewData and
would have public properties to hold the data elements to be passed on to the view.
(Suggested by http://weblogs.asp.net/scottgu/archive/2007/12/06/asp-net-mvc-
framework-part-3-passing-viewdata-from-controllers-to-views.aspx.) For organization
purposes, the view data DTOs should be placed within the controllers which they
support. So the aforementioned example would be referenced via
ProductsController.ListViewData.
For creating and editing an item, the "New" action should be invoked to initialize a form.
The form should then submit itself to the "Create" action which will handle capturing the
form data and saving the data item. (Suggested by
http://weblogs.asp.net/scottgu/archive/2007/12/09/asp-net-mvc-framework-part-4-
handling-form-edit-and-post-scenarios.aspx.)

Within the Tests Layer
      Test classes should be organized under sub-folders, having one sub-folder for
       each layer being tested. For example, a folder would be added to
       ProjectName.Tests called ProjectName.Core. This folder would contain all the
       test fixtures for testing the Projectname.Core assembly.
      The default namespace of this class library should be changed to “Tests” to avoid
       namespace ambiguity.

Managing Solution Items
Whenever possible, assembly dependencies should never be placed into the GAC.
Instead, application dependencies should be maintained in a folder called “Solution
Items” which resides in the root of the source directory. This facilitates multiple
applications on a single server using different versions of an assembly.

NHibernate
      Set “inverse=true” on the parent in a bi-directional parent/child relationship to
       avoid foreign key constraint violations (NRD 6.5 Lazy Initialization).
      For organization purposes, only declare one class per HBM.
      For maintainability and convenience, keep HBMs right next to the objects they
       describe in the ProjectName.Core assembly.

Microformats
Per http://microformats.org/wiki/Main_Page, “microformats are small bits of HTML that
represent things like people, events, tags, etc. in web pages. Microformats enable the
publishing of higher fidelity information on the Web, providing the fastest and simplest
way to support feeds and APIs for your website.”

To be more concise, microformats are industry accepted standards for facilitating
semantic XHTML. CSS should be used to alter look and layout of microformat output.

The following microformat standards should be followed when applicable:
    hCard (http://microformats.org/wiki/hcard) for people, companies, organizations,
       and places.
    hCalendar (http://microformats.org/wiki/hcalendar) for calendaring and events.
    hReview (http://microformats.org/wiki/hreview) for reviews of products, services,
       business, events, etc.
    XFN (http://www.gmpg.org/xfn/) for organizational information, relationships,
       and social networks.
    XOXO (http://microformats.org/wiki/xoxo) for outlines.
      If another microformat is available for the information being displayed, use when
       appropriate.

Common Development Problems & Exceptions
Exception Troubleshooting
Exception: Reference to unmapped class
Fix: It is usually because the NHibernate HBM is not configured to be an embedded
resource. Right click the newly added HBM, click properties, and then set its
compilation mode to “Embedded Resource.”

Exception: Unable to load one or more of the requested types. Retrieve the
LoaderExceptions property for more information. (If the page is refreshed, it may then
say “The controller for path … could not be found…”
Fix: This is actually a mask over another exception due to the ASP.NET MVC
framework. To see the actual exception, add the following code to
Global.Application_Error: Exception exception = Server.GetLastError().
Then, place a breakpoint on the closing tag of Global.Application_Error and run the
application in debug mode. The exception variable in the debug window will hold the
details of the underlying exception.

Exception: Error activating <some object>: no matching bindings are available, and the
type is not self-bindable (or implicit binding is disabled). Activation path: 1) active
request for <some object>
Fix: This is indicative that Ninject is attempting to perform dependency injection of an
object that it is not aware of. To fix this, the binding for the object in question needs to
be added to a Ninject module under the MyProject.Web/NinjectModules folder.

Problem: Your host will not support running the application in Full Trust.
Fix: If you must run in a Medium Trust environment, the following modifications must
be made to the NHibernate configuration:
  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
      <bytecode-provider type="null"/>
      <session-factory>
          …
          <property name="current_session_context_class">managed_web</property>
          <mapping assembly="Northwind.Core"/>
      </session-factory>
  </hibernate-configuration>


Additionally, all class mappings need to be set to lazy=”false”.

Appendix A: Resources
Referenced Works
[NBP]
NHibernate Best Practices with ASP.NET, 1.2nd Ed.
http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx
Contains detailed background materials and theory related to S#arp Architecture. The
CodeProject article is the predecessor to the current architecture.

[NRD]
NHibernate Reference Documentation Version 1.2.0.
http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/.
The definitive reference guide to NHibernate.

								
To top