DEV Community

Discussion on: Kentico 12: Design Patterns Part 20 - Choosing a Solution Architecture

Collapse
 
seangwright profile image
Sean G. Wright • Edited

I just realized I might have skipped answering your specific question 🤦‍♂️!

If you are using an Onion architecture, then you should have a domain class (HomePageData) that is in your Core project. By having it there you can't take a dependency on your data access implementation project (let's call it Data).

This means HomePageData will need to have a constructor that only accepts:

  • Primitive .NET type parameters
  • Other types in your Core project

So you can't use the generated HomePage page type class as a parameter.

Each layer should own its abstractions, which means the HomePageData and (if you are using a repository pattern) the IHomePageRepository should be defined in Core, while the Data project will have an implementation of IHomePageRepository which will return HomePageData.

Core

  • HomePageData (domain class)
  • IHomePageRepository (domain abstraction)

Data

  • HomePage (custom page type class)
  • KenticoHomePageRepository (implementation of domain abstraction)

Now your presentation project (let's call it Web) will rely on the abstraction and domain type and never access the types in Data directly:

public class HomePageController : Controller
{
    private readonly IHomePageRepository repo;

    public HomePageController(IHomePageRepository repo) => this.repo = repo;

    public ActionResult Index()
    {
        HomePageData data = repo.GetHomePage();

        return View(new HomePageViewModel(data));
    }
}

Notice here that it's ok for the HomePageViewModel to depend on the domain abstraction HomePageData - domain types are meant to be used everywhere since they don't have any volatile dependencies themselves, instead it's the implementations that we want to keep isolated.