Merge pull request #12267 from abpframework/auto-merge/rel-5-2/990

Merge branch dev with rel-5.2
pull/12268/head
liangshiwei 4 years ago committed by GitHub
commit e4663f495f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,7 @@
# Switch to EF Core MySQL Provider
> [ABP CLI](CLI.md) and the [Get Started](https://abp.io/get-started) page already provides an option to create a new solution with MySQL. See [that document](Entity-Framework-Core-Other-DBMS.md) to learn how to use. This document provides guidance for who wants to manually switch to MySQL after creating the solution.
This document explains how to switch to the **MySQL** database provider for **[the application startup template](Startup-Templates/Application.md)** which comes with SQL Server provider pre-configured.
## Replace the Volo.Abp.EntityFrameworkCore.SqlServer Package

@ -1,5 +1,7 @@
# Switch to EF Core Oracle Provider
> [ABP CLI](CLI.md) and the [Get Started](https://abp.io/get-started) page already provides an option to create a new solution with Oracle. See [that document](Entity-Framework-Core-Other-DBMS.md) to learn how to use. This document provides guidance for who wants to manually switch to Oracle after creating the solution.
This document explains how to switch to the **Oracle** database provider for **[the application startup template](Startup-Templates/Application.md)** which comes with SQL Server provider pre-configured.
ABP Framework provides integrations for two different Oracle packages. See one of the following documents based on your provider decision:

@ -1,15 +1,32 @@
# Switch to Another DBMS for Entity Framework Core
**[The application startup template](Startup-Templates/Application.md)** comes with **SQL Server provider pre-configured** for the Entity Framework Core. However, EF Core supports [many other DBMSs](https://docs.microsoft.com/en-us/ef/core/providers/) and you can use any of them within your ABP based applications.
[ABP CLI](CLI.md) provides a `-dbms` option to allow you to choose your Database Management System (DBMS) while creating a new solution. It accepts the following values:
ABP framework provides **integration packages** for some common DBMSs to make the configuration a bit easier. You can use the following documents to learn how to **switch to your favorite DBMS**:
- `SqlServer` (default)
- `MySQL`
- `SQLite`
- `Oracle`
- `Oracle-Devart`
- `PostgreSQL`
So, if you want to use MySQL for your solution, you can use the `-dbms MySQL` option while using the `abp new` command. Example:
````bash
abp new BookStore -dbms MySQL
````
Also, the [Get Started page](https://abp.io/get-started) on the ABP website allows you to select one of the providers.
> **This document provides guidance for who wants to manually change their DBMS after creating the solution.**
You can use the following documents to learn how to **switch to your favorite DBMS**:
* [MySQL](Entity-Framework-Core-MySQL.md)
* [PostgreSQL](Entity-Framework-Core-PostgreSQL.md)
* [Oracle](Entity-Framework-Core-Oracle.md)
* [SQLite](Entity-Framework-Core-SQLite.md)
However, you can configure your DBMS provider **without** these integration packages. While using the integration package is always recommended (it also makes standard for the depended version across different modules), you can do it manually if there is no integration package for your DBMS provider.
You can also configure your DBMS provider **without** these integration packages. While using the integration package is always recommended (it also makes standard for the depended version across different modules), you can do it yourself if there is no integration package for your DBMS provider.
For an example, this document explains how to switch to MySQL without using [the MySQL integration package](Entity-Framework-Core-MySQL.md).

@ -1,5 +1,7 @@
# Switch to EF Core PostgreSQL Provider
> [ABP CLI](CLI.md) and the [Get Started](https://abp.io/get-started) page already provides an option to create a new solution with PostgreSQL. See [that document](Entity-Framework-Core-Other-DBMS.md) to learn how to use. This document provides guidance for who wants to manually switch to PostgreSQL after creating the solution.
This document explains how to switch to the **PostgreSQL** database provider for **[the application startup template](Startup-Templates/Application.md)** which comes with SQL Server provider pre-configured.
## Replace the Volo.Abp.EntityFrameworkCore.SqlServer Package

@ -1,5 +1,7 @@
# Switch to EF Core SQLite Provider
> [ABP CLI](CLI.md) and the [Get Started](https://abp.io/get-started) page already provides an option to create a new solution with SQLite. See [that document](Entity-Framework-Core-Other-DBMS.md) to learn how to use. This document provides guidance for who wants to manually switch to SQLite after creating the solution.
This document explains how to switch to the **SQLite** database provider for **[the application startup template](Startup-Templates/Application.md)** which comes with SQL Server provider pre-configured.
## Replace the Volo.Abp.EntityFrameworkCore.SqlServer Package

@ -423,7 +423,7 @@ namespace MyProject.Issues
## Integration Tests
> You can follow the [web application development tutorial](Tutorials/Part-1.md) to learn developing a full stack application, including the integration tests.
> You can also follow the [web application development tutorial](Tutorials/Part-1.md) to learn developing a full stack application, including the integration tests.
### The Integration Test Infrastructure
@ -442,7 +442,7 @@ Using in-memory SQLite database has two main advantages;
### The Seed Data
Writing tests against an empty database is not practical. In most cases, you need to some initial data in the database. For example, if you write a test class that query, update and delete the Products, it would be helpful to have a few products in the database before executing the test case.
Writing tests against an empty database is not practical. In most cases, you need to some initial data in the database. For example, if you write a test class that query, update and delete the products, it would be helpful to have a few products in the database before executing the test case.
ABP's [Data Seeding](Data-Seeding.md) system is a powerful way to seed the initial data. The application startup template has a *YourProject*TestDataSeedContributor class in the `.TestBase` project. You can fill it to have an initial data that you can use for each test method.
@ -649,6 +649,101 @@ namespace MyProject.Issues
It's that simple. This test method tests everything, including the application service, EF Core mapping, object to object mapping and the repository implementation. In this way, you can fully test the Application Layer and the Domain Layer of your solution.
### Dealing with Unit of Work in Integration Tests
ABP's [unit of work](Unit-Of-Work.md) system controls the database connection and transaction management in your application. It seamlessly works while you writing your application code, so you may not aware of it.
In the ABP Framework, all the database operations must be performed inside a unit of work scope. When you test an [application service](Application-Services.md) method, the unit of work scope will be the scope of your application service method. If you are testing a [repository](Repositories.md) method, the unit of work scope will be the scope of your repository method.
In some cases, you may need to manually control the unit of work scope. Consider the following test method:
````csharp
public class IssueRepository_Tests : MyProjectDomainTestBase
{
private readonly IRepository<Issue, Guid> _issueRepository;
public IssueRepository_Tests()
{
_issueRepository = GetRequiredService<IRepository<Issue, Guid>>();
}
public async Task Should_Query_By_Title()
{
IQueryable<Issue> queryable = await _issueRepository.GetQueryableAsync();
var issue = queryable.FirstOrDefaultAsync(i => i.Title == "My issue title");
issue.ShouldNotBeNull();
}
}
````
We are using `_issueRepository.GetQueryableAsync` to obtain an `IQueryable<Issue>` object. Then, we are using the `FirstOrDefaultAsync` method to query an issue by its title. The database query is executed at this point, and you get an exception indicating that there is no active unit of work.
To make that test properly working, you should manually start a unit of work scope as shown in the following example:
````csharp
public class IssueRepository_Tests : MyProjectDomainTestBase
{
private readonly IRepository<Issue, Guid> _issueRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager;
public IssueRepository_Tests()
{
_issueRepository = GetRequiredService<IRepository<Issue, Guid>>();
_unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
}
public async Task Should_Query_By_Title()
{
using (var uow = _unitOfWorkManager.Begin())
{
IQueryable<Issue> queryable = await _issueRepository.GetQueryableAsync();
var issue = queryable.FirstOrDefaultAsync(i => i.Title == "My issue title");
issue.ShouldNotBeNull();
await uow.CompleteAsync();
}
}
}
````
We've used the `IUnitOfWorkManager` service to create a unit of work scope, then called the `FirstOrDefaultAsync` method inside that scope, so we don't have the problem anymore.
> Note that we've tested the `FirstOrDefaultAsync` to demonstrate the unit of work problem. Normally, as a good principle, you should write tests only your own code.
### Working with DbContext
In some cases, you may want to directory work with the Entity Framework's `DbContext` object to perform database operations in your test methods. In this case, you can use `IDbContextProvider<T>`service to obtain a `DbContext` instance inside a unit of work.
The following example shows how you can create a `DbContext` object in a test method:
````csharp
public class MyDbContext_Tests : MyProjectDomainTestBase
{
private readonly IDbContextProvider<MyProjectDbContext> _dbContextProvider;
private readonly IUnitOfWorkManager _unitOfWorkManager;
public IssueRepository_Tests()
{
_dbContextProvider = GetRequiredService<IDbContextProvider<MyProjectDbContext>>();
_unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
}
public async Task Should_Query_By_Title()
{
using (var uow = _unitOfWorkManager.Begin())
{
var dbContext = await _dbContextProvider.GetDbContextAsync();
var issue = await dbContext.Issues.FirstOrDefaultAsync(i => i.Title == "My issue title");
issue.ShouldNotBeNull();
await uow.CompleteAsync();
}
}
}
````
Just like we've done in the *Dealing with Unit of Work in Integration Tests* section, we should perform `DbContext` operations inside an active unit of work.
For [MongoDB](MongoDB.md), you can use the `IMongoDbContextProvider<T>` service to obtain a `DbContext` object and directly use MongoDB APIs in your test methods.
## UI Tests
In general, there are two types of UI Tests;

@ -34,7 +34,7 @@ public static class UnitOfWorkExtensions
{
Check.NotNull(unitOfWork, nameof(unitOfWork));
return unitOfWork.Items.FirstOrDefault(x => x.Key == key).As<TValue>();
return unitOfWork.Items.FirstOrDefault(x => x.Key == key).Value.As<TValue>();
}
public static TValue GetOrAddItem<TValue>([NotNull] this IUnitOfWork unitOfWork, string key, Func<string, TValue> factory)

@ -0,0 +1,58 @@
using Shouldly;
using Volo.Abp.Testing;
using Xunit;
namespace Volo.Abp.Uow;
public class UnitOfWorkExtensions_Tests : AbpIntegratedTest<AbpUnitOfWorkModule>
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
public UnitOfWorkExtensions_Tests()
{
_unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
}
[Fact]
public void AddItem()
{
var uow = _unitOfWorkManager.Begin();
uow.AddItem("testKey", "testValue");
uow.Items.ShouldContainKey("testKey");
uow.Items.ContainsValue("testValue");
}
[Fact]
public void GetItemOrDefault()
{
var uow = _unitOfWorkManager.Begin();
uow.Items.Add("testKey", new NameValue("TestKey","TestValue"));
uow.GetItemOrDefault<NameValue>("testKey").ShouldBeOfType<NameValue>();
uow.GetItemOrDefault<NameValue>("testKey").Value.ShouldBe("TestValue");
}
[Fact]
public void GetOrAddItem()
{
var uow = _unitOfWorkManager.Begin();
var item = uow.GetOrAddItem("testKey", _ => new NameValue("TestKey", "TestValue"));
item.Name.ShouldBe("TestKey");
item.ShouldBeOfType<NameValue>();
item.Value.ShouldBe("TestValue");
}
[Fact]
public void RemoveItem()
{
var uow = _unitOfWorkManager.Begin();
uow.Items.Add("testKey", "testValue");
uow.RemoveItem("testKey");
uow.Items.ShouldNotContainKey("testKey");
}
}

@ -1,4 +1,4 @@
<div class="container">
<div class="container">
<div class="card">
<div class="card-header">
<h5 class="card-title">
@ -9,4 +9,33 @@
{{ '::Welcome_Text' | abpLocalization }}
</div>
</div>
</div>
<div class="card mt-5">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;"
class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete
understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0"
class="btn btn-success mb-1">
Buy on Amazon US
</a>
&nbsp;
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242"
class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -11,4 +11,29 @@
@L["Welcome_Text"]
</div>
</div>
<div class="card mt-5">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1">
Buy on Amazon US
</a>
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -11,4 +11,29 @@
@L["Welcome_Text"]
</div>
</div>
<div class="card mt-5">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1">
Buy on Amazon US
</a>
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -21,4 +21,29 @@
@L["Welcome_Text"]
</abp-card-body>
</abp-card>
<div class="card mt-5">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1">
Buy on Amazon US
</a>
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -21,4 +21,29 @@
@L["Welcome_Text"]
</abp-card-body>
</abp-card>
<div class="card mt-5">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1">
Buy on Amazon US
</a>
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -11,9 +11,38 @@
<p class="lead px-lg-5 mx-lg-5">{{ '::LongWelcomeMessage' | abpLocalization }}</p>
<a *ngIf="!hasLoggedIn" (click)="login()" class="px-4 btn btn-primary ms-1" role="button"
><i class="fa fa-sign-in"></i> {{ 'AbpAccount::Login' | abpLocalization }}</a
><i class="fa fa-sign-in"></i> {{ 'AbpAccount::Login' | abpLocalization }}</a
>
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;"
class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete
understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0"
class="btn btn-success mb-1">
Buy on Amazon US
</a>
&nbsp;
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242"
class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="my-3 text-center">
<h3>Let's improve your application!</h3>
<p>Here are some links to help you get started:</p>
@ -268,13 +297,13 @@
<div class="mb-5 text-center">
<p class="align-middle">
<a href="https://twitter.com/abpframework" target="_blank" class="mx-2"
><i class="fa fa-twitter"></i><span class="text-secondary"> Abp Framework</span></a
><i class="fa fa-twitter"></i><span class="text-secondary"> Abp Framework</span></a
>
<a href="https://twitter.com/abpcommercial" target="_blank" class="mx-2"
><i class="fa fa-twitter"></i><span class="text-secondary"> Abp Commercial</span></a
><i class="fa fa-twitter"></i><span class="text-secondary"> Abp Commercial</span></a
>
<a href="https://github.com/abpframework/abp" target="_blank" class="mx-2"
><i class="fa fa-github"></i><span class="text-secondary"> abpframework</span></a
><i class="fa fa-github"></i><span class="text-secondary"> abpframework</span></a
>
</p>
</div>
@ -296,7 +325,7 @@
[href]="link.href"
target="_blank"
class="btn btn-link px-1"
>{{ link.label }} <i class="fas fa-chevron-right"></i
>{{ link.label }} <i class="fas fa-chevron-right"></i
></a>
</div>
</div>
@ -309,7 +338,7 @@
<i class="fas fa-plus d-block mb-3 fa- 2x text-secondary"></i>
<span [innerHTML]="context.title"></span>
<a [href]="context.href" target="_blank" class="d-block mt-2 btn btn-sm btn-link"
>Details <i class="fas fa-chevron-right"></i
>Details <i class="fas fa-chevron-right"></i
></a>
</h6>
</div>

@ -12,13 +12,38 @@
<h1>Welcome to the Application</h1>
<p class="lead px-lg-5 mx-lg-5">@L["LongWelcomeMessage"]</p>
@if (!CurrentUser.IsAuthenticated)
{
<a class="btn btn-primary" href="/Account/Login" ><i class="fa fa-sign-in"></i> @L["Login"]</a>
<a class="btn btn-primary" href="/Account/Login"><i class="fa fa-sign-in"></i> @L["Login"]</a>
}
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1">
Buy on Amazon US
</a>
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="my-3 text-center">
<h3>Let's improve your application!</h3>
<p>Here are some links to help you get started:</p>

@ -15,10 +15,35 @@
@if (!CurrentUser.IsAuthenticated)
{
<a class="btn btn-primary" href="Account/Login" ><i class="fa fa-sign-in"></i> @L["Login"]</a>
<a class="btn btn-primary" href="Account/Login"><i class="fa fa-sign-in"></i> @L["Login"]</a>
}
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1">
Buy on Amazon US
</a>
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="my-3 text-center">
<h3>Let's improve your application!</h3>
<p>Here are some links to help you get started:</p>

@ -21,6 +21,31 @@
}
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1">
Buy on Amazon US
</a>
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="my-3 text-center">
<h3>Let's improve your application!</h3>
<p>Here are some links to help you get started:</p>

@ -6,10 +6,10 @@
@inject IHtmlLocalizer<MyProjectNameResource> L
@inject ICurrentUser CurrentUser
@section styles {
<abp-style src="/Pages/Index.css" />
<abp-style src="/Pages/Index.css" />
}
@section scripts {
<abp-script src="/Pages/Index.js" />
<abp-script src="/Pages/Index.js" />
}
<div class="container">
<div class="p-5 text-center">
@ -22,10 +22,34 @@
@if (!CurrentUser.IsAuthenticated)
{
<a abp-button="Primary" href="~/Account/Login" ><i class="fa fa-sign-in"></i> @L["Login"]</a>
<a abp-button="Primary" href="~/Account/Login"><i class="fa fa-sign-in"></i> @L["Login"]</a>
}
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1">
Buy on Amazon US
</a>
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="my-3 text-center">
<h3>Let's improve your application!</h3>
<p>Here are some links to help you get started:</p>

@ -6,10 +6,10 @@
@inject IHtmlLocalizer<MyProjectNameResource> L
@inject ICurrentUser CurrentUser
@section styles {
<abp-style src="/Pages/Index.css" />
<abp-style src="/Pages/Index.css" />
}
@section scripts {
<abp-script src="/Pages/Index.js" />
<abp-script src="/Pages/Index.js" />
}
<div class="container">
<div class="p-5 text-center">
@ -22,10 +22,34 @@
@if (!CurrentUser.IsAuthenticated)
{
<a abp-button="Primary" href="~/Account/Login" ><i class="fa fa-sign-in"></i> @L["Login"]</a>
<a abp-button="Primary" href="~/Account/Login"><i class="fa fa-sign-in"></i> @L["Login"]</a>
}
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-auto text-center">
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3">
</div>
<div class="col-md d-flex align-items-center">
<div class="pe-0 pe-md-4">
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small>
<h2 class="mb-4">Mastering ABP Framework</h2>
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p>
<div class="mb-4">
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1">
Buy on Amazon US
</a>
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1">
Buy on PACKT
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="my-3 text-center">
<h3>Let's improve your application!</h3>
<p>Here are some links to help you get started:</p>

Loading…
Cancel
Save