[go: up one dir, main page]

Open Source Framework

The open-source ABP Framework stands at the heart of the ABP Platform.

ABP Framework is a complete infrastructure for creating software solutions with modern architectures based on the ASP.NET Core platform.

Source Code

Architecture

Modern architecture to create maintainable software solutions.

Microservice Compatible

The core ABP Framework & all the pre-built modules are designed with microservice architecture in mind.

Domain Driven Design

It helps in implementing a DDD-based layered architecture and creating a maintainable code base.

Modular Architecture

The modular system allows you to develop reusable application modules, connect to application lifecycle events and decouple the dependencies.

Multi-tenancy

SaaS applications made easy! Integrated multi-tenancy from database to UI.

Framework Features

Multiple UI Options

ABP offers multiple options for creating the UI layer. You can always use your own UI technology, but starting with ready-made solutions will speed you up extra.

Multiple Database Providers

The framework can work with any data source, while the following providers are officially developed and supported:

ABP CLI

ABP CLI is a command line tool to perform common development tasks for ABP-based solutions.


                              # Create a new layered application
                              abp new Acme.BookStore

                              # Create a new layered application using MongoDB
                              abp new Acme.BookStore -d mongodb

                              # Add a new module to the solution
                              abp add-module Volo.Blogging
                        

Modularity

ABP provides a complete infrastructure to build your own application modules that may have entities, services, database integration, APIs, UI components and so on..

[DependsOn(
   typeof(AbpEntityFrameworkCoreModule), //Depending on a framework module
   typeof(MyBusinessModule) //Depending on your own module
)]
public class MyAppModule : AbpModule
{
   public override void ConfigureServices(ServiceConfigurationContext context)
   {
      //Configure DI and other modules...
   }

   public override void OnApplicationInitialization(ApplicationInitializationContext context)
   {
      //Perform some application initialization logic...
   }
}

Multi-tenancy

ABP doesn't only support developing multi-tenant applications, but also makes your code mostly unaware of the multi-tenancy. It can automatically determine the current tenant, isolate data of different tenants from each other. It supports single database, database per tenant and hybrid approaches.

You focus on your business code and let the framework handle multi-tenancy on behalf of you.

Bootstrap Tag Helpers

Instead of manually writing the repeating details of bootstrap components, use ABP's tag helpers to simplify it and take advantage of the IntelliSense. You can directly use Bootstrap whenever you need it.

Code:
<abp-card>
   <img abp-card-image="Top" src="" data-src="/images/my-dog.png" class="lazy" loading="lazy"
width="250" heigth="162"/>
   <abp-card-body>
      <abp-card-title>Card title</abp-card-title>
      <abp-card-text>
            <p>
            This is a sample card component built by ABP bootstrap
            card tag helper. ABP has tag helper wrappers for most of
            the bootstrap components.
            </p>
      </abp-card-text>
      <a abp-button="Primary" href="javascript:void(0)"  >Go somewhere &rarr;</a>
   </abp-card-body>
</abp-card>
Result:
Bootstrap Tag Helper
Card title

This is a sample card component built by ABP bootstrap card tag helper.

Go somewhere →

Dynamic Forms

Dynamic form & input tag helpers can create the complete form from a C# class as the model.

View:
<abp-dynamic-form abp-model="@Model.PersonInput" submit-button="true" />
Model:
public class PersonModel
{
   [HiddenInput]
   public Guid Id { get; set; }

   [Required]
   [EmailAddress]
   [StringLength(255)]
   public string Email { get; set; }

   [Required]
   [StringLength(32)]
   [DataType(DataType.Password)]
   public string Password { get; set; }

   [StringLength(255)]
   public string Address { get; set; }

   public Gender Gender { get; set; }
}
Result:
*
*

Authentication & Authorization

Rich authentication & authorization options integrated to ASP.NET Core Identity & OpenIddict. Provides an extensible & detailed permission system.

Cross Cutting Concerns

Don't repeat yourself to implement all this common stuff again & again. Focus on your business code and let ABP automate them by conventions.

Concurrency Check

ABP provides an optimistic concurrency check mechanism to ensure data consistency in your application and prevents users access or change the same data in a database at the same time.

public class Book : Entity<Guid>, IHasConcurrencyStamp
{
    public string ConcurrencyStamp { get; set; }

    //...
}

Bundling & Minification

ABP offers a simple, dynamic, powerful, modular and built-in bundling & minification system.

<abp-style-bundle name="MyGlobalBundle">
   <abp-style src="/libs/bootstrap/css/bootstrap.css" />
   <abp-style src="/libs/font-awesome/css/font-awesome.css" />
   <abp-style src="/libs/toastr/toastr.css" />
   <abp-style src="/styles/my-global-style.css" />
</abp-style-bundle>

Virtual File System

The Virtual File System makes it possible to manage files that do not physically exist on the file system (disk). It's mainly used to embed the (js, css, image, cshtml...) files into assemblies and use them like physical files on runtime.

Theming

Theming system allows developing your application & modules theme independent by defining a set of common base libraries and layouts, based on the latest Bootstrap framework.

Theming

Background Jobs

Define simple classes to execute jobs in the background as queued. Use the built-in job manager or integrate your own. Hangfire, RabbitMQ and Quartz integrations are already available.

public class EmailSendingJob : BackgroundJob<EmailSendingArgs>
{
   private readonly IEmailSender _emailSender;

   public EmailSendingJob(IEmailSender emailSender)
   {
      _emailSender = emailSender;
   }

   public override void Execute(EmailSendingArgs args)
   {
      _emailSender.Send(
            args.EmailAddress,
            args.Subject,
            args.Body
      );
   }
}

Background Workers

Define operations to run in a separate, dedicated thread. Use the built-in background workers or integrate your own. Hangfire and Quartz integrations are already available.

public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase
{
    public PassiveUserCheckerWorker(
            AbpAsyncTimer timer,
            IServiceScopeFactory serviceScopeFactory
        ) : base(
            timer, 
            serviceScopeFactory)
    {
        Timer.Period = 6000;
    }

    protected async override Task DoWorkAsync(
        PeriodicBackgroundWorkerContext workerContext)
    {
        Logger.LogInformation("Starting: Setting status of inactive users...");

        //Resolve dependencies
        var userRepository = workerContext
            .ServiceProvider
            .GetRequiredService<IUserRepository>();

        //Do the work
        await userRepository.UpdateInactiveUserStatusesAsync();

        Logger.LogInformation("Completed: Setting status of inactive users...");
    }
}

Domain Driven Design Infrastructure

A complete infrastructure to build layered applications based on the Domain Driven Design patterns & principles;

public class BookAppService : ApplicationService, IBookAppService
{
   private readonly IRepository<Book, Guid> _bookRepository;

   public BookAppService(IRepository<Book, Guid> bookRepository)
   {
      _bookRepository = bookRepository;
   }

   public async Task CreateAsync(CreateBookDto input)
   {
      var book = new Book(
            GuidGenerator.Create(),
            input.Name,
            input.Type,
            input.Price
      );

      await _bookRepository.InsertAsync(book);
   }
}

Auto REST APIs

ABP can automatically configure your application services as API Controllers by convention.

Auto Rest APIs

Cancellation Support

ABP allows for the graceful termination of asynchronous operations in applications, ensuring proper resource cleanup and responsive user experience.

Dynamic Client Proxies

Easily consume your APIs from JavaScript and C# clients.

//Call remote APIs just like local functions in JavaScript
acme.bookStore.book
   .getList({})
   .done(function (result) {
      //...
   });

Distributed Event Bus

Easily publish & consume distributed events using built-in Distributed Event Bus with RabbitMQ, Kafka, Rebus and Azure integrations

Publish Events:
public class PublisherDemo : ITransientDependency
{
   private readonly IDistributedEventBus _distributedEventBus;

   public PublisherDemo(
      IDistributedEventBus distributedEventBus)
   {
      _distributedEventBus = distributedEventBus;
   }

   public async Task RunAsync()
   {
      //Publish an event
      await _distributedEventBus.PublishAsync(
            new StockCountChangedEvent(productId, 42)
      );
   }
}
Handle Events:
public class MyEventHandler
   : IDistributedEventHandler<StockCountChangedEvent>
{
   public Task HandleEventAsync(StockCountChangedEvent eventData)
   {
         //Handle the event and execute your business
   }
}

Distributed Locking

ABP's distributed locking system ensures that resources are accessed in a mutually exclusive manner across different nodes in a distributed environment, preventing concurrent conflicts and ensuring data consistency.

using Volo.Abp.DistributedLocking; 

namespace AbpDemo
{
    public class MyService : ITransientDependency
    {
      private readonly IAbpDistributedLock _distributedLock;
      
      public MyService(IAbpDistributedLock distributedLock)
        {
            _distributedLock = distributedLock;
        }

        public async Task MyMethodAsync()
        {
            await using (var handle = await _distributedLock.TryAcquireAsync("MyLockName"))
            {
                if (handle != null)
                {
                    // your code that access the shared resource
                }
            }   
        }
    }
}

BLOB Storing

BLOB Storing system provides an abstraction to work with BLOBs. ABP provides some pre-built storage provider integrations (Azure, AWS, File System, Database, etc.) that you can easily use in your applications.

public class MyService : ITransientDependency
{
   private readonly IBlobContainer _blobContainer;

   public MyService(IBlobContainer blobContainer)
   {
      _blobContainer = blobContainer;
   }

   public async Task SaveBytesAsync(byte[] bytes)
   {
      await _blobContainer.SaveAsync("my-blob", bytes);
   }

   public async Task<byte[]> GetBytesAsync()
   {
      return await _blobContainer.GetAllBytesOrNullAsync("my-blob");
   }
}

Text Templating

Text templating is used to dynamically render contents based on a template and a model (a data object). For example, you can use it to create dynamic email contents with a pre-built template.

var result = await _templateRenderer.RenderAsync(
   "PasswordReset", //the template name
   new PasswordResetModel
   {
      Name = "john",
      Link = "https://abp.io/example-link?userId=123&token=ABC"
   }
);

Test Infrastructure

The framework has been developed with unit & integration testing in mind. Provides you base classes to make it easier. Startup templates come pre-configured for testing.

public class MyService_Tests : AbpIntegratedTest<MyModule>
{
   private readonly MyService _myService;

   public MyService_Tests()
   {
      _myService = GetRequiredService<MyService>();
   }

   [Fact]
   public async Task MyService_Should_Do_It()
   {
      //Act
      var result = _myService.DoIt();

      //Assert
      result.ShouldBe(42);
   }
}

Audit Logging & Entity Histories

Built-in audit logging for business-critical applications. Request, service, method level audit logging and entity histories with property-level details.

Object to Object Mapping

Object to object mapping abstraction with AutoMapper integration.

public class PersonService
{
   //Inject IObjectMapper
   private readonly IObjectMapper _objectMapper;

   public PersonService(IObjectMapper objectMapper)
   {
      _objectMapper = objectMapper;
   }

   public PersonDto GetPerson(Guid id)
   {
      Person person = GetPersonEntityFromRepository(id);

      //Use for Entity to DTO mapping
      return _objectMapper.Map<Person, PersonDto>(person);
   }
}

Email & SMS Abstractions with Templating Support

IEmailSender and ISmsSender abstractions decouples your application logic from the infrastructure. Advanced email template system allows to create & localize email templates and easily use whenever needed.

public async Task SendWelcomeEmailAsync(string emailAddress, string name)
{
   //Get the email template
   var template = await _emailTemplateProvider.GetAsync("WelcomeEmailTemplate");

   //Replace placeholders
   template.Replace("name", name);

   //Send email
   await _emailSender.SendAsync(
      emailAddress,
      "Welcome to our application!",
      template.Content
   );
}

Localization

Localization system allows creating resources in plain JSON files and uses them to localize your UI. It supports advanced scenarios like inheritance, extensions and JavaScript integration while it is fully compatible with AspNet Core's localization system.

{
   "culture": "en",
   "texts": {
      "WelcomeMessage": "Welcome to the application!",
      "HelloWorld":  "Hello World"
   }
}

Setting Management

Define settings for your application and get the values on runtime based on the current configuration, tenant and user.

Extension Methods & Helpers

Don't repeat yourself even for trivial code parts. Extensions & helpers for standard types make your code much cleaner and easy to write.

//Convert a string to camelCase
"HelloWorld".ToCamelCase(); //returns "helloWorld"

//Truncate a string with "..." postfix
"This is a test string".TruncateWithPostfix(12); //returns "This is a..."

//Convert a string to int
"42".To<int>(); //returns 42 as int

//Check if a value occurs in a list
5.IsIn(1, 3, 5, 7); //returns true

//Check if a value is between a range
5.IsBetween(6, 12); //returns false

Aspect Oriented Programming

Provides a comfortable infrastructure to create dynamic proxies and implement Aspect Oriented Programming. Intercept any class and execute your code before & after every method execution.

//Inherit from the AbpInterceptor to log all method executions
public class MyLoggingInterceptor : AbpInterceptor, ITransientDependency
{
   private readonly ILogger<MyLoggingInterceptor> _logger;

   public MyLoggingInterceptor(ILogger<MyLoggingInterceptor> logger)
   {
      _logger = logger;
   }

   public async override Task InterceptAsync(IAbpMethodInvocation invocation)
   {
      LogInvocation(invocation);
      await invocation.ProceedAsync();
   }

   private void LogInvocation(IAbpMethodInvocation invocation)
   {
      /* Access to all the information about the method execution
         * including method, class and provided arguments */

      _logger.LogInformation(
            "Executing the method: " +
            invocation.Method.Name +
            " of class " +
            invocation.TargetObject.GetType().FullName
      );
   }
}

Dependency Injection by Conventions

No need to register your classes to dependency injection manually. Automatically registers common service types by convention. For other type of services, you can use interfaces and attributes to make it easier and in-place.

/* Automatically registers MyService as transient.
* Then you can inject by IMyService or MyService.
*/
public class MyService : IMyService, ITransientDependency
{
}

Data filtering

Define and use data filters that are automatically applied when you query entities from the database. Soft Delete & MultiTenant filters are provided out of the box when you implement simple interfaces.

public class MyEntity : Entity<Guid>, ISoftDelete
{
   public bool IsDeleted { get; set; }
}

Encryption & Decryption Services

ABP provides string encryption feature that allows to Encrypt and Decrypt strings.

 public class MyService : DomainService
 {
     protected IStringEncryptionService StringEncryptionService { get; }

     public MyService(IStringEncryptionService stringEncryptionService)
     {
         StringEncryptionService = stringEncryptionService;
     }

     public string Encrypt(string value)
     {
         // To enrcypt a value
         return StringEncryptionService.Encrypt(value);
     }

     public string Decrpyt(string value)
     {
         // To decrypt a value
         return StringEncryptionService.Decrypt(value);
     }
 }