Introducing an Application Framework For ASP.Net MVC

Contents

  • Introduction
  • A Quick Sample
  • What Else
  • Startup Templates
  • How To Use
Introduction

We are creating various applications based on different needs. But implementing common and similar structures over and over again, at least at 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 are that lucky. Most of them have no time, budget and team to develop such frameworks. They might not even be able to create a framework, it's hard to document and train developers and maintain it.

ASP.NET Boilerplate (ABP) is an open-source and well documented application framework that began the 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:

  1. public class TaskAppService : ApplicationService, ITaskAppService  
  2. {  
  3.     private readonly IRepository<Task> _taskRepository;  
  4.   
  5.     public TaskAppService(IRepository<Task> taskRepository)  
  6.     {  
  7.         _taskRepository = taskRepository;  
  8.     }  
  9.   
  10.     [AbpAuthorize(MyPermissions.UpdatingTasks)]  
  11.     public async Task UpdateTask(UpdateTaskInput input)  
  12.     {  
  13.         Logger.Info("Updating a task for input: " + input);  
  14.   
  15.         var task = await _taskRepository.FirstOrDefaultAsync(input.TaskId);  
  16.         if (task == null)  
  17.         {  
  18.             throw new UserFriendlyException(L("CouldNotFoundTheTaskMessage"));  
  19.         }  
  20.   
  21.         input.MapTo(task);  
  22.     }  

Here, we see a sample Application Service method. An application service, in DDD, is directly used by the presentation layer to perform use cases of the application. We can think that the 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 a 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). The default repository has many useful methods as was FirstOrDefault used in this example. We can easily extend the default repository upon our needs. Repositories abstract DBMS and ORMs and simplifies data access logic.
  • Authorization: ABP can check permissions. It prevents access to an UpdateTask method if the current user has no "updating task" permission or is not logged in. It simplifies authorization using declarative attributes but also has additional ways of authorization.
  • Validation: ABP automatically checks if the input is null. It also validates all the properties of an input based on standard data annotation attributes and custom validation rules. If the 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 the default. It automatically creates a connection and begins a transaction at the beggining of the method. If the method was successfully completed without exception, then the transaction is commited and the connection is disposed of. Even this method uses different repositories or methods, all of them will be atomic (transactional). And all changes on entities are automatically saved when the transaction is commited. Thus, we don't even need to call the _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, then it returns a JSON to the client to indicate that an error occured. It hides the actual exception from client unless the exception is a UserFriendlyException as used in this sample. It also understands and handles errors on the client side and shows an appropriate messages to users.
  • Logging: As you see, we can write logs using the Logger object defined in the base class. Log4Net is used as the default but it's changable or configurable.
  • Localization: Notice that we used an L method when throwing an exception. Thus, it's automatically localized based on the current user's culture. Surely, we're defining CouldNotFoundTheTaskMessage somewhere.
  • Auto Mapping: In the last line, we're using ABP's MapTo extension method to map input properties to entity properties. It uses the AutoMapper library to do the 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 (there is 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 at runtime. Thus, we can use application service methods directly from clients.
  • Dynamic JavaScript AJAX Proxy: ABP creates JavaScript proxy methods to make calling application service methods just as simple as calling JavaScript methods on the client.

We can see the benefits of ABP in such a simple class. All these tasks normally require a significiant amount of time, but they are all automatically handled by ABP.

What Else

Beside this simple example, ABP provides a strong infrastructure and application model. Here, some other features of ABP are:

  • 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 supports single-database multi-customer style multi-tenancy.
  • Setting Management: Provides a strong infrastructure to get/change application, tenant and user level settings.
  • Unit & Integration Testing: It's built with testability in mind. Also provides base classes to simplify unit & integration tests.
Startup Templates

Starting a new solution, creating layers, installing Nuget packages, creating a simple layout and a menu. All these are very time consuming stuff.

ASP.NET Boilerplate provides pre-built startup templates that make starting a new solution much easier. Templates support Single-Page Application (SPA) and Multi-Page MVC Application (MPA) architectures. Also, allows us to use various ORMs.

How To Use

ASP.NET Boilerplate is developed on Github and distributed on Nuget. The easiest way to start with ABP is to create a startup template and follow the documentation.


Similar Articles