Introduction
We are creating different applications based on different needs.
But implementing common and similar structures over and over again, at
least in some level. Authorization, Validation,
Exception Handling, Logging, Localization,
Database Connection Management, Setting Management,
Audit Logging are some of these common structures. Also, we
are building architectural structures and best practices like
Layered and Modular Architecture, Domain Driven Design,
Dependency Injection and so on. And trying to
develop applications based on some conventions.
Since all of these are very time-consuming and hard to build seperately for
every project, many companies
create private frameworks. They're developing new applications
faster with less bugs using these frameworks. Surely, not all companies that
lucky. Most of them have no time, budget and
team to develop such frameworks. Even they have possibility to
create a framework, it's hard to document, train
developers and maintain it.
ASP.NET Boilerplate (ABP) is an open source and well documented
application framework started idea of "developing a common
framework for all companies and all developers!" It's not just a
framework but also provides a strong architectural model based
on Domain Driven Design and best practices in
mind.
A Quick Sample
Let's investigate a simple class to see ABP's benefits:
public class TaskAppService : ApplicationService, ITaskAppService
{
private readonly IRepository<Task> _taskRepository;
public TaskAppService(IRepository<Task> taskRepository)
{
_taskRepository = taskRepository;
}
[AbpAuthorize(MyPermissions.UpdatingTasks)]
public async Task UpdateTask(UpdateTaskInput input)
{
Logger.Info("Updating a task for input: " + input);
var task = await _taskRepository.FirstOrDefaultAsync(input.TaskId);
if (task == null)
{
throw new UserFriendlyException(L("CouldNotFoundTheTaskMessage"));
}
input.MapTo(task);
}
}
Here, we see a sample
Application Service method. An application service, in DDD, is directly used
by presentation layer to perform use cases of the application.
We can think that UpdateTask method is called by javascript via
AJAX. Let's see ABP's some benefits here:
-
Dependency
Injection
: ABP uses and provides a strong and conventional DI
infrastructure. Since this class is an application service, it's
conventionally registered to DI container as transient (created per
request). It can simply inject all dependencies (as IRepository<Task> in
this sample).
-
Repository
:
ABP can create a default repository for each entity (as IRepository<Task> in
this example). Default repository has many useful methods as FirstOrDefault
used in this example. We can easily extend default repository upon our
needs. Repositories abstracts DBMS and ORMs and simplifies data access
logic.
-
Authorization
:
ABP can check permissions. It prevents access to UpdateTask method if
current user has no "updating task" permission or not logged in. It
simplifies authorization using declarative attributes but also has
additional ways of authorization.
-
Validation
: ABP automatically checks if input is null. It also
validates all properties of an input based on standard data annotation
attributes and custom validation rules. If request is not valid, it throws a
proper validation exception.
-
Audit Logging
:
User, browser, IP address, calling service, method, parameters, calling
time, execution duration and some other informations are automatically saved
for each request based on conventions and configurations.
-
Unit Of Work
:
In ABP, each application service method is assumed as a unit of work as
default. It automatically creates a connection and begins a transaction at
the beggining of the method. If the method successfully completed without
exception, then the transaction is commited and connection is disposed. Even
this method uses different repositories or methods, all of them will be
atomic (transactional). And all changes on entities are automatically saved
when transaction is commited. Thus, we don't even need to call
_repository.Update(task) method as shown here.
-
Exception
Handling
: We almost never handle exceptions in ABP in a web
application. All exceptions are automatically handled by default. If an
exception occurs, ABP automatically logs it and returns a proper result to
the client. For example, if this is an AJAX request, the it returns a JSON
to client indicates that an error occured. If hides actual exception from
client unless the exception is a UserFriendlyException as used in this
sample. It also understands and handles errors on client side and show
appropriate messages to users.
-
Logging
: As you
see, we can write logs using the Logger object defined in base class.
Log4Net is used as default but it's changable or configurable.
-
Localization
:
Notice that we used L method while throwing exception. Thus, it's
automatically localized based on current user's culture. Surely, we're
defining CouldNotFoundTheTaskMessage in somewhere
(see localization document for more).
-
Auto Mapping
:
In the last line, we're using ABP's MapTo extension method to map input
properties to entity properties. It uses AutoMapper library to perform
mapping. Thus, we can easily map properties from one object to another based
on naming conventions.
-
Dynamic Web API Layer
:
TaskAppService is a simple class actually (even no need to deliver from
ApplicationService). We generally write a wrapper Web API Controller to
expose methods to javascript clients. ABP automatically does that on
runtime. Thus, we can use application service methods directly from clients.
-
Dynamic Javascript AJAX Proxy
: ABP creates javascript proxy
methods those make calling application service methods just as simple as
calling javascript methods on the client.
We can see benefit of ABP in such a simple class. All these tasks normally
take significiant time, but all they are automatically handled by ABP.
What Else
Beside this simple example, ABP provides a strong infrastructure and
application model. Here, some other features of ABP:
-
Modularity
:
Provides a strong infrastructure to build reusable modules.
-
Data Filters
:
Provides automatic data filtering to implement some patterns like
soft-delete and multi-tenancy.
-
Multi Tenancy: It
fully supports multi-tenancy, including single database or
database per tenant architectures.
-
Setting Management
:
Provides a strong infrastructure to get/change application, tenant and user
level settings.
-
Unit & Integration Testing: It's built testability in
mind. Also provides base classes to simplify unit & integration tests. See
this article for more information.
For all features, see documentation.
Startup Templates
Starting a new solution, creating layers, installing nuget packages, creating
a simple layout and a menu... all these are also time consuming stuff.
ABP provides pre-built
startup templates that
makes starting a new solution is much more easier. Templates support SPA
(Single-Page Application) and MPA (Multi-Page MVC Applications)
architectures. Also, allows us to use different ORMs.
How To Use
ABP is developed on
Github
and
distributed on
Nuget
.
Easiest way of starting with ABP is creating a
startup template and
following the documentation.