Skip to content

ASP.NET

Martin Havlišta edited this page Sep 11, 2018 · 40 revisions

WORK IN PROGRESS

Follow these steps to use CoreDdd in ASP.NET MVC application (tested with Visual Studio 2017 and .NET Framework 4.6.1):

  1. Create a new ASP.NET MVC project.
  2. Install following nuget packages into the project:
  1. Pick you favourite IoC container to register CoreDdd services. CoreDdd supports Castle Windsor via following nuget packages:

And Ninject via following nuget packages:

For other IoC containers, manual registration of CoreDdd services into IoC container is needed.

  1. Add a new empty NHibernate configurator class, example:
    public class CoreDddSampleNhibernateConfigurator : NhibernateConfigurator
    {
        protected override Assembly[] GetAssembliesToMap()
        {
            return new Assembly[0];
        }
    }
  1. Add a new NHibernate config file hibernate.cfg.xml . Here is SQLite example:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>

    <property name="connection.connection_string">Data Source=CoreDddSampleAspNetWebApp.db</property>
    <property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
    <property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
    <property name="connection.release_mode">on_close</property>

    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="show_sql">false</property>
    <property name="proxyfactory.factory_class">NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate</property>
    <property name="transaction.use_connection_on_system_prepare">false</property>

  </session-factory>
</hibernate-configuration>
  1. Install System.Data.SQLite.Core nuget package. Version 1.0.108 needs to be manually installed via command Install-Package System.Data.SQLite.Core -Version 1.0.108 from Package Manager Console (Tools -> Nuget Package Manager -> Package Manager Console; current latest version 1.0.109.1 is broken). For different databases, please look at Entity database persistence.

  2. Add the following code into MvcApplication.Application_Start() in Global.asax.cs to register CoreDdd services:

Castle Windsor IoC container:

    var iocContainer = new WindsorContainer();

    CoreDddNhibernateInstaller.SetUnitOfWorkLifeStyle(x => x.PerWebRequest);

    iocContainer.Install(
        FromAssembly.Containing<CoreDddInstaller>(),
        FromAssembly.Containing<CoreDddNhibernateInstaller>()
    );
    iocContainer.Register(
        Component
            .For<INhibernateConfigurator>()
            .ImplementedBy<CoreDddSampleNhibernateConfigurator>()
            .LifestyleSingleton()
    );

Ninject IoC container (needs also Ninject.Web.Common, Ninject.MVC5 nuget packages installed):

    var iocContainer = new StandardKernel();

    CoreDddNhibernateBindings.SetUnitOfWorkLifeStyle(x => x.InRequestScope());

    iocContainer.Load(
        typeof(CoreDddBindings).Assembly,
        typeof(CoreDddNhibernateBindings).Assembly
    );
    iocContainer
        .Bind<INhibernateConfigurator>()
        .To<CoreDddSampleNhibernateConfigurator>()
        .InSingletonScope();

For other IoC containers, check out the CoreDdd services and CoreDdd.Nhibernate services registrations for an inspiration how various CoreDdd services should be registered into an IoC container.

  1. To handle each web request within ADO.NET transaction:

Add the following code into web.config (under system.webServer - modules):

      <add name="UnitOfWork" type="CoreDdd.AspNet.HttpModules.UnitOfWorkHttpModule, CoreDdd.AspNet" preCondition="managedHandler" />
      <add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" preCondition="managedHandler" />

and add the following code to MvcApplication.Application_Start() to initialize UnitOfWorkHttpModule:

Castle Windsor IoC container example:

    UnitOfWorkHttpModule.Initialize(iocContainer.Resolve<IUnitOfWorkFactory>());

Ninject IoC container example:

    UnitOfWorkHttpModule.Initialize(iocContainer.Get<IUnitOfWorkFactory>());

To handle each web request within a transaction scope with ADO.NET connection enlisted in the TransactionScope, add the following code into web.config (under system.webServer - modules) :

      <add name="TransactionScopeUnitOfWork" type="CoreDdd.AspNet.HttpModules.TransactionScopeUnitOfWorkHttpModule, CoreDdd.AspNet" preCondition="managedHandler" />
      <add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" preCondition="managedHandler" />

and add the following code to MvcApplication.Application_Start() to initialize TransactionScopeUnitOfWorkHttpModule:

Castle Windsor IoC container example:

    Action<TransactionScope> transactionScopeEnlistmentAction = transactionScope =>
    {
        // enlist custom resource manager into the transaction scope
    };
    TransactionScopeUnitOfWorkHttpModule.Initialize(
        iocContainer.Resolve<IUnitOfWorkFactory>(),
        transactionScopeEnlistmentAction: transactionScopeEnlistmentAction
    );

Ninject IoC container example:

    Action<TransactionScope> transactionScopeEnlistmentAction = transactionScope =>
    {
        // enlist custom resource manager into the transaction scope
    };
    TransactionScopeUnitOfWorkHttpModule.Initialize(
        iocContainer.Get<IUnitOfWorkFactory>(),
        transactionScopeEnlistmentAction: transactionScopeEnlistmentAction
    );
  1. Add a controller factory into the project:

Castle Windsor IoC container example:

    public class IoCContainerCastleWindsorControllerFactory : DefaultControllerFactory
    {
        private readonly IWindsorContainer _iocContainer;

        public IoCContainerCastleWindsorControllerFactory(IWindsorContainer iocContainer)
        {
            _iocContainer = iocContainer;
        }

        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                return base.GetControllerInstance(requestContext, null);
            }

            var controller = (IController)_iocContainer.Resolve(controllerType);
            return controller;
        }

        public override void ReleaseController(IController controller)
        {
            _iocContainer.Release(controller);
            base.ReleaseController(controller);
        }
    }

Ninject IoC container example:

    public class IoCContainerNinjectControllerFactory : DefaultControllerFactory
    {
        private readonly IResolutionRoot _iocContainer;

        public IoCContainerNinjectControllerFactory(IResolutionRoot iocContainer)
        {
            _iocContainer = iocContainer;
        }

        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                return base.GetControllerInstance(requestContext, null);
            }

            var controller = (IController)_iocContainer.Get(controllerType);
            return controller;
        }

        public override void ReleaseController(IController controller)
        {
            _iocContainer.Release(controller);
            base.ReleaseController(controller);
        }
    }

And set the controller factory in MvcApplication.Application_Start():

Castle Windsor IoC container example:

    ControllerBuilder.Current.SetControllerFactory(new IoCContainerCastleWindsorControllerFactory(iocContainer));

Ninject IoC container example:

    ControllerBuilder.Current.SetControllerFactory(new IoCContainerNinjectControllerFactory(iocContainer));

The code above is available as a sample ASP.NET MVC application here. The sample application also contains ShipController with methods to create a new Ship aggregate root domain entity, query ships by name and update ship data.

You can check out other wiki pages how to persist an entity, query data, modify an application state or create more complex DDD implementation.

Clone this wiki locally