ASP.NET Boilerplate v3.4 has just been released (see change logs). In this article, I will highlight some new features and changes.


We were in NDC London 2018 Conference as a partner

Entity History

This was one of the most wanted features for a long time and it’s finally available.

Once you configure it for your entities, it can automatically write audit logs for every property change of an entity. There are three concepts for a database change:

  • Entity Change Set: A set of changes in a single database save operation. It may contain one or more entity changes.
  • Entity Change: A change (create, update or delete) for an entity. It belongs to an entity change set.
  • Entity Property Change: A single property change of an entity. It belongs to an entity change.

So, for a relational database, all these changes are stored in three tables:


Entity history tables in a relational database

How to Enable?

It’s enabled by default, but this just enables logging the entity history. You should also enable it for your entities in PreInitialize method of your module. Example:

Configuration.EntityHistory.Selectors.Add("MyProjectEntities", typeof(Product), typeof(Order), typeof(Customer));

This code enables the entity history logging for Product, Order and Customer entities. “MyProjectEntities” is just a unique name for this configuration (then another module can remove the configuration by this name).

How to Change the Store?

ASP.NET Boilerplate is an extensible framework. If you want to write entity history logs to another destination (for example, to a non-relational database or to a 3rd-party log provider), you can just replace the IEntityHistoryStore by your own implementation.

OData AspNetCore Integration

With v3.4 release, introduced the Abp.AspNetCore.OData package. It’s an integration package to use OData for ASP.NET Core within ASP.NET Boilerplate based projects easier.

See documentation for OData AspNetCore Integration.

Allow Modules to Configure MVC Routes

One problem with modular approach is that every module may want to contribute to the main application configuration. Route definition is one example.

A classic route definition for an ASP.NET Core MVC application is something like that:

app.UseMvc(routes =>
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}"

This code stands in Startup file and an independent module can not access to that code to add it’s own route definitions.

With the ABP v3.4 release, we introduced a configuration point for routes. Now, a module can add a route definition (or modify existing routes) using such a code in the PreInitialize method of the module class:

public class MyModule : AbpModule
  public override void PreInitialize()
    .RouteConfiguration.Add(routes =>
        name: "blog",
        template: "Blog/{*article}",
        defaults: new {controller = "Blog", action = "ReadArticle"}

Any module can contribute to the route configuration like that. Finally, we should modify the app.UseMvc statement to add all routes from the configuration:

app.UseMvc(routes =>

Default Security Headers

As OWASP recommends, ASP.NET Boilerplate v3.4 adds some default headers to HTTP responses for security purposes:

  • X-Content-Type-Options = nosniff
  • X-XSS-Protection = 1; mode=block
  • X-Frame-Options = SAMEORIGIN

If you want to disable it, you can do it on app.UseAbp in your Startup file as shown below:

app.UseAbp(options =>
  options.UseSecurityHeaders = false;


See Github change logs for all feature and enhancements in this release:

What’s Next

Recently, we introduced ASP.NET Boilerplate to Microsoft ASP.NET development team at NDC London 2018. They liked it much and will help this project to gain more community.


Our first goal is to provide more introduction tutorials/videos and make it easier to start with ASP.NET Boilerplate framework. For enhancements and new features, follow the Github issues and milestones.