Developer Guides

Few words about architecture of GrandNode

Most of the projects, directories, and files are named so that you can get a rough idea of their purpose. For example, I don't even have to look inside the project called Grand.Plugin.Payments.PayPalStandard to guess what it does.




The Grand.Core project contains a set of core classes for GrandNode, such as caching, events, helpers, and business objects (for example, Order and Customer entities).


This project contains a set of core services, business logic, validations or calculations related with the data, if needed. Some people call it Business Access Layer (BAL).


Grand.Web.Framework is a class library project containing some common presentation things for both Grand.Admin and Grand.Web projects.

Projects into \Plugins\ solution folder

\Plugins is a Visual Studio solution folder that contains plugin projects. Physically it's located in the root of your solution. But plugins DLLs are automatically copied in \Presentation\Grand.Web\Plugins\ directory which is used for already deployed plugins because the build output paths of all plugins are set to "..\..\Presentation\Grand.Web\Plugins\{Group}.{Name}\". This allows plugins to contain some external files, such as static content (CSS or JS files) without having to copy files between projects to be able to run the project.


Grand.Web is also an MVC web application project, a presentation layer for public store. This is the application that you actually run. It is the startup project of the application.


Grand.Core.Tests is the test project for the Grand.Core project.


Grand.Services.Tests is the test project for the Grand.Services project.


Grand.Services.Tests is the test project for the Grand.Services project.


Grand.Services.Tests is the test project for the Grand.Services project.



- Service

Service is plain implementation of Interface, a convenient layer between repository and Controllers (worth to mention – Services should be used only by Controllers – and inside Controllers shouldn’t be any operation on repository).

You should use these structures consistent with thier purpose.

Of course, why don't request Repository straight from Controller. It is so straightforward (it is not an advice).



To enable access to database and its collections with records, you need to declare IRepostiory<DomainModel>


IRepository’s implementation is MongoDBRepository<DomainModel>


MongoDBRepository (definition of Repository layer) does direct operations on database



- Dependencies

Inversion of Control and Dependency Injection are two related ways to break apart dependencies in your applications. Inversion of Control (IoC) means that objects do not create other objects on which they rely to do their work. Instead, they get the objects that they need from an outside source. Dependency Injection (DI) means that this is done without the object intervention, usually by a framework component that passes constructor parameters and sets properties. Martin Fowler has written a great description of Dependency Injection or Inversion of Control. I'm not going to duplicate his work, and you can find his article here. GrandNode uses Autofac library as its IoC container. Once a service and an appropriate interface, which the service implements, are written you should register them in any class implementing the IDependencyRegistrar interface (Grand.Core.Infrastructure.DependencyManagement namespace). For example, all core GrandNode services are registered in the DependencyRegistrar class located in the Grand.Web.Framework library.

idepandancy registrar

You can create as many dependency registrar classes as you need. Each class implementing IDependencyRegistrar interface has an Order property. It allows you to replace existing dependencies. To override GrandNode dependencies, set the Order property to something greater than 0. GrandNode orders dependency classes and runs them in ascending order. The higher the number the later your objects will be registered.

folder view

class example


HERE you can see source code of examples used in this documentation.

back to top