Features

ABP CLI

ABP CLI (Command Line Interface) is a command line tool to perform some common operations 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     


See the CLI document for more information

Modularity

ABP provides a complete infrastructure to build your own application modules those 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...
    }
}


See the module development document for more information

Multi-Tenancy

ABP framework not only supports to develop multi-tenant applications, but also makes your code mostly unaware of the multi-tenancy.

Can automatically determine the current tenant, isolate data of different tenants from each other.

Supports single database, database per tenant and hybrid approaches.

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


See the multi-tenancy document for more information

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 intellisense. You can definitely use Bootstrap whenever you need it.

Code:

 
<abp-card>
    <img abp-card-image="Top" src="~/images/my-dog.png" />
    <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="#">Go somewhere &rarr;</a>
    </abp-card-body>
</abp-card>

Result:

Card title

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

Go somewhere →

See the tag helpers document for more information

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:

*
*

See the dynamic forms document for more information

Authentication & Authorization

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


See the authorization document for more information.

Cross Cutting Concerns

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

Bundling & Minification

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


See the bundling & minification document for more information

 
<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 those do not physically exist on the file system (disk). It's mainly used to embed (js, css, image, cshtml...) files into assemblies and use them like physical files on runtime.


See the virtual file system document for more information

Theming

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


See the theming document for more information

Background Jobs

Define simple classes to execute jobs in background as queued. Use built-in job manager or integrate your own. HangFire & RabbitMQ integrations are already available.


See the background jobs document for more information

 

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
        );
    }
}

Domain Driven Design Infrastructure

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


See the domain driven design document for more information

 
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 automagically configure your application services as API Controllers by convention.


See the auto API controllers document for more information

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) {
        //...
    });
    

See the dynamic client proxy documentations for JavaScript & C#.

Distributed Event Bus with RabbitMQ Integration

Easily publish & consume distributed events using built-in Distributed Event Bus with RabbitMQ integration available.

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
    }
}


See the distributed event bus document for more information

Test Infrastructure

The framework has been developed unit & integration testing in mind. Provides you base classes to make it easier. Startup templates come with 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);
    }
}
                    

See the testing document for more information

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.


See the audit logging document for more information

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);
    }
}


See the object mapping document for more information

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
    );
}
                    

See the emailing and SMS sending documents for more information.

Localization

Localization system allows to create resources in plain JSON files and use 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"
  }
}


See the localization document for more information

Setting Management

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


See the settings document for more information

Extension Methods & Helpers

Don't repeat yourself even for trivial code parts. Extensions & helpers for standard types makes 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
                    

See the xtension methods & helpers document for more information

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 override async 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
        );
    }
}


See the aspect oriented programming document for more information

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
{
}
                    

See the dependency injection document for more information

Data filtering

Define and use data filters those are automatically applied when you query entities from 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; }
}


See the data filtering document for more information