Skip to content

ASP.NET Core rules

Starter project

The ASP.NET starter project is an architecture guidance for beginners, use it as a baseline.

Business logic

The business logic layer should always be a separate project and have absolutely no reference to the website.

The business logic layer cannot contain:

  • ViewModels
  • Any data formatting logic for the user interface (for example, converting a DateTime to a "mm/dd/yyyy" format string)
  • Any logic related to the design (for example, HTML markup or CSS styles)

In addition to logical reasons, this is also necessary so that business logic can be reused in related projects.

Data formatting

In any project, it is required to display the date, time, numbers and money in a certain format. For example, the requirements might be:

  • Date format: mm/dd/yyyy.
  • Format for currency: "$10" for dollars and "10 EUR" for euros.
  • Format for integers: "1".
  • Format for decimal numbers: "1.00".

IMPORTANT

All code responsible for formatting should be in one place!

For example, it could be a helper class that can be called from anywhere in the application:

csharp
FormattingHelper.DateTimeToString()
FormattingHelper.DateToString()
FormattingHelper.TimeToString()
FormattingHelper.DecimalToString()
FormattingHelper.CurrencyToString()

The purpose of all this is that if the format requirements change (for example, replacing mm/dd/yyyy with dd/mm/yyyy), it would need to be changed in only one place.

Formatting and AutoMapper

If the project uses AutoMapper, then formatting must be done using ValueResolvers:

csharp
configuration.CreateMap<User, UserListViewModel>()
.ForMember(d => d.CompanyName, o => o.MapFrom(s => s.Company.Name))
.ForMember(d => d.CreateDate, o => o.ResolveUsing<DateToFormattedStringResolver>().FromMember(s => s.CreateDate));

DateToFormattedStringResolver (derived from ValueResolver) can internally call FormatingHelper.

Controllers

Controllers should only be responsible for the user interface, so they should only containt the user interface logic.

Controllers should not have:

  • Business logic (should be in the business layer)
  • Mapping logic, i.e. logic for converting domain models into view models

As a result, controllers should be as compact and clear as possible.

In most cases, the mapping logic must be described using AutoMapper mappings.

In rare cases, when you have to fill the ViewModel manually without using AutoMapper, you should place the mapping logic to a special mapping class, such as UserMapper.

Made by Entrypoint with ❤️