Skip to content

Commit

Permalink
Merge pull request abpframework#5 from abpframework/dev
Browse files Browse the repository at this point in the history
merge
  • Loading branch information
marcelo-maciel authored Oct 20, 2019
2 parents d84bcb4 + 8998b23 commit 1139f57
Show file tree
Hide file tree
Showing 2,197 changed files with 146,229 additions and 65,979 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ public class AbpIoLocalizationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<VirtualFileSystemOptions>(options =>
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpIoLocalizationModule>("AbpIoLocalization");
});

Configure<ExceptionLocalizationOptions>(options =>
Configure<AbpExceptionLocalizationOptions>(options =>
{
options.MapCodeNamespace("Volo.AbpIo.Commercial", typeof(AbpIoCommercialResource));
options.MapCodeNamespace("Volo.AbpIo.Domain", typeof(AbpIoBaseResource));
Expand Down
3 changes: 2 additions & 1 deletion docs/en/AspNetCore/Client-Side-Package-Management.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ An example mapping configuration is shown below:
````js
mappings: {
"@node_modules/bootstrap/dist/css/bootstrap.css": "@libs/bootstrap/css/",
"@node_modules/bootstrap/dist/js/bootstrap.bundle.js": "@libs/bootstrap/js/"
"@node_modules/bootstrap/dist/js/bootstrap.bundle.js": "@libs/bootstrap/js/",
"@node_modules/bootstrap-datepicker/dist/locales/*.*": "@libs/bootstrap-datepicker/locales/"
}
````

Expand Down
6 changes: 3 additions & 3 deletions docs/en/Caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

ABP framework extends ASP.NET Core's distributed caching system.

## IDistributedCache Interface
## `IDistributedCache` Interface

ASP.NET Core defines the `IDistributedCache` interface to get/set cache values. But it has some difficulties:

Expand All @@ -17,7 +17,7 @@ ASP.NET Core defines the `IDistributedCache` interface to get/set cache values.
See [ASP.NET Core's distributed caching document](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) for more information.

## IDistributedCache<TCacheItem> Interface
## `IDistributedCache<TCacheItem>` Interface

ABP framework defines the generic `IDistributedCache<TCacheItem>` interface in the [Volo.Abp.Caching](https://www.nuget.org/packages/Volo.Abp.Caching/) package. `TCacheItem` is the type of the object stored in the cache.

Expand Down Expand Up @@ -82,4 +82,4 @@ Other methods of the `IDistributedCache<BookCacheItem>` are same as ASP.NET Core

### DistributedCacheOptions

TODO
TODO
2 changes: 1 addition & 1 deletion docs/en/Getting-Started-Angular-Template.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Hit F5 (or Ctrl+F5) to run the application. It will have an output like shown be

#### Using EF Core Update-Database Command

Ef Core has `Update-Database` command which creates database if necessary and applies pending migrations. Right click to the `.Web` project and select **Set as StartUp Project**:
Ef Core has `Update-Database` command which creates database if necessary and applies pending migrations. Right click to the `.HttpApi.Host` project and select **Set as StartUp Project**:

![set-as-startup-project](images/set-as-startup-project.png)

Expand Down
115 changes: 43 additions & 72 deletions docs/en/Getting-Started-AspNetCore-Application.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ This tutorial explains how to start ABP from scratch with minimal dependencies.

## Create A New Project

1. Create a new empty AspNet Core Web Application from Visual Studio:
1. Create a new AspNet Core Web Application from Visual Studio 2019 (16.3.0+):

![](images/create-new-aspnet-core-application.png)
![](images/create-new-aspnet-core-application-v2.png)

2. Select Empty Template
2. Configure your new project:

![](images/select-empty-web-application.png)
![](images/select-empty-web-application-v2.png)

You could select another template, but I want to show it from a clear project.
3. Press to the create button:

![create-aspnet-core-application](D:\Github\abp\docs\en\images\create-aspnet-core-application.png)

## Install Volo.Abp.AspNetCore.Mvc Package

Expand All @@ -28,10 +30,8 @@ ABP is a modular framework and it requires a **startup (root) module** class der

````C#
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Volo.Abp;
using Volo.Abp.AspNetCore.Modularity;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;

Expand All @@ -40,7 +40,8 @@ namespace BasicAspNetCoreApplication
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
public class AppModule : AbpModule
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
public override void OnApplicationInitialization(
ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
Expand All @@ -49,37 +50,40 @@ namespace BasicAspNetCoreApplication
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}

app.UseMvcWithDefaultRoute();
app.UseStaticFiles();
app.UseRouting();
app.UseMvcWithDefaultRouteAndArea();
}
}
}
````

``AppModule`` is a good name for the startup module for an application.

ABP packages define module classes and a module can depend on another module. In the code above, our ``AppModule`` depends on ``AbpAspNetCoreMvcModule`` (defined by Volo.Abp.AspNetCore.Mvc package). It's common to add a ``DependsOn`` attribute after installing a new ABP nuget package.
ABP packages define module classes and a module can depend on another. In the code above, the ``AppModule`` depends on the ``AbpAspNetCoreMvcModule`` (defined by [Volo.Abp.AspNetCore.Mvc](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc) package). It's common to add a ``DependsOn`` attribute after installing a new ABP nuget package.

Instead of Startup class, we are configuring ASP.NET Core pipeline in this module class.
Instead of the Startup class, we are configuring ASP.NET Core pipeline in this module class.

## The Startup Class

Next step is to modify Startup class to integrate to ABP module system:

````C#
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace BasicAspNetCoreApplication
{
public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AppModule>();

return services.BuildServiceProviderFromFactory();
}

public void Configure(IApplicationBuilder app)
Expand All @@ -88,41 +92,19 @@ namespace BasicAspNetCoreApplication
}
}
}

````

Changed ``ConfigureServices`` method to return ``IServiceProvider`` instead of ``void``. This change allows us to replace AspNet Core's Dependency Injection with another framework (see Autofac integration section below). ``services.AddApplication<AppModule>()`` adds all services defined in all modules beginning from the ``AppModule``.
``services.AddApplication<AppModule>()`` adds all services defined in all modules starting from the ``AppModule``.

``app.InitializeApplication()`` call in ``Configure`` method initializes and starts the application.
``app.InitializeApplication()`` in ``Configure`` method initializes and starts the application.

## Hello World!
## Run the Application!

The application above does nothing. Let's create an MVC controller does something:

````C#
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;

namespace BasicAspNetCoreApplication.Controllers
{
public class HomeController : AbpController
{
public IActionResult Index()
{
return Content("Hello World!");
}
}
}

````

If you run the application, you will see a "Hello World!" message on the page.

Derived ``HomeController`` from ``AbpController`` instead of standard ``Controller`` class. This is not required, but ``AbpController`` class has useful base properties and methods to make your development easier.
That's all! Run the application, it will just work as expected.

## Using Autofac as the Dependency Injection Framework

While AspNet Core's Dependency Injection (DI) system is fine for basic requirements, Autofac provides advanced features like Property Injection and Method Interception which are required by ABP to perform advanced application framework features.
While AspNet Core's Dependency Injection (DI) system is fine for basic requirements, [Autofac](https://autofac.org/) provides advanced features like Property Injection and Method Interception which are required by ABP to perform advanced application framework features.

Replacing AspNet Core's DI system by Autofac and integrating to ABP is pretty easy.

Expand All @@ -143,40 +125,29 @@ public class AppModule : AbpModule
}
````

3. Change ``services.AddApplication<AppModule>();`` line in the ``Startup`` class as shown below:

````C#
services.AddApplication<AppModule>(options =>
{
options.UseAutofac(); //Integrate to Autofac
});
````

4. Update `Program.cs` to not use the `WebHost.CreateDefaultBuilder()` method since it uses the default DI container:
3. Update `Program.cs` to use Autofac:

````csharp
public class Program
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace BasicAspNetCoreApplication
{
public static void Main(string[] args)
public class Program
{
/*
https://github.com/aspnet/AspNetCore/issues/4206#issuecomment-445612167
CurrentDirectoryHelpers exists in: \framework\src\Volo.Abp.AspNetCore.Mvc\Microsoft\AspNetCore\InProcess\CurrentDirectoryHelpers.cs
Will remove CurrentDirectoryHelpers.cs when upgrade to ASP.NET Core 3.0.
*/
CurrentDirectoryHelpers.SetCurrentDirectory();

BuildWebHostInternal(args).Run();
}
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IWebHost BuildWebHostInternal(string[] args) =>
new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIIS()
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac(); //Add this line
}
}
````

Expand Down
Binary file added docs/en/images/create-aspnet-core-application.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
85 changes: 85 additions & 0 deletions docs/zh-Hans/Caching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# 缓存

ABP框架扩展了ASP.NET Core的分布式缓存系统.

## `IDistributedCache` 接口

ASP.NET Core 定义了 `IDistributedCache` 接口用于 get/set 缓存值 . 但是会有以下问题:

* 它适用于 **byte 数组** 而不是 .NET 对象. 因此你需要对缓存的对象进行**序列化/反序列化**.
* 它为所有的缓存项提供了 **单个 key 池** , 因此 ;
* 你需要注意键区分 **不同类型的对象**.
* 你需要注意**不同租户**(参见[多租户](Multi-Tenancy.md))的缓存项.

> `IDistributedCache` 定义在 `Microsoft.Extensions.Caching.Abstractions` 包中. 这使它不仅适用于ASP.NET Core应用程序, 也可用于**任何类型的程序**.
> `IDistributedCache` 接口的默认实现是 `MemoryDistributedCache` 它使用**内存**工作. 参见 [ASP.NET Core文档](https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed) 了解如何切换到 **Redis** 或其他缓存提供程序.
有关更多信息, 参见 [ASP.NET Core 分布式缓存文档](https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed).

## `IDistributedCache<TCacheItem>` 接口

ABP框架在[Volo.Abp.Caching](https://www.nuget.org/packages/Volo.Abp.Caching/)包定义了通用的泛型 `IDistributedCache<TCacheItem>` 接口. `TCacheItem` 是存储在缓存中的对象类型.

`IDistributedCache<TCacheItem>` 接口了上述中的问题;

* 它在内部 **序列化/反序列化** 缓存对象. 默认使用 **JSON** 序列化, 但可以替换[依赖注入](Dependency-Injection.md)系统中 `IDistributedCacheSerializer` 服务的实现来覆盖默认的处理.
* 它根据缓存中对象类型自动向缓存key添加 **缓存名称** 前缀. 默认缓存名是缓存对象类的全名(如果你的类名以`CacheItem` 结尾, 那么`CacheItem` 会被忽略,不应用到缓存名称上). 你也可以在缓存类上使用 `CacheName` 设置换缓存的名称.
* 它自动将当前的**租户id**添加到缓存键中, 以区分不同租户的缓存项 (只有在你的应用程序是[多租户](Multi-Tenancy.md)的情况下生效). 在缓存类上应用 `IgnoreMultiTenancy` attribute, 可以在所有的租户间共享缓存.
* 允许为每个应用程序定义 **全局缓存键前缀** ,不同的应用程序可以在共享的分布式缓存中拥有自己的隔离池.

### 使用方式

缓存中存储项的示例类:

````csharp
public class BookCacheItem
{
public string Name { get; set; }

public float Price { get; set; }
}
````

你可以注入 `IDistributedCache<BookCacheItem>` 服务用于 get/set `BookCacheItem` 对象.

使用示例:

````csharp
public class BookService : ITransientDependency
{
private readonly IDistributedCache<BookCacheItem> _cache;

public BookService(IDistributedCache<BookCacheItem> cache)
{
_cache = cache;
}

public async Task<BookCacheItem> GetAsync(Guid bookId)
{
return await _cache.GetOrAddAsync(
bookId.ToString(), //Cache key
async () => await GetBookFromDatabaseAsync(bookId),
() => new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
}
);
}

private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
{
//TODO: get from database
}
}
````

* 示例服务代码中的 `GetOrAddAsync()` 方法从缓存中获取图书项.
* 如果没有在缓存中找到图书,它会调用工厂方法 (本示例中是 `GetBookFromDatabaseAsync`)从原始数据源中获取图书项.
* `GetOrAddAsync` 有一个可选参数 `DistributedCacheEntryOptions` , 可用于设置缓存的生命周期.

`IDistributedCache<BookCacheItem>` 的其他方法与ASP.NET Core的`IDistributedCache` 接口相同, 你可以参考 [ASP.NET Core文档](https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed).

### DistributedCacheOptions

TODO
3 changes: 2 additions & 1 deletion docs/zh-Hans/docs-nav.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
"text": "授权"
},
{
"text": "缓存"
"text": "缓存",
"path": "Caching.md"
},
{
"text": "审计"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class AbpAspNetCoreMultiTenancyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<TenantResolveOptions>(options =>
Configure<AbpTenantResolveOptions>(options =>
{
options.TenantResolvers.Add(new QueryStringTenantResolveContributor());
options.TenantResolvers.Add(new RouteTenantResolveContributor());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class AspNetCoreMultiTenancyOptions
public class AbpAspNetCoreMultiTenancyOptions
{
/// <summary>
/// Default: <see cref="TenantResolverConsts.DefaultTenantKey"/>.
/// </summary>
public string TenantKey { get; set; }

public AspNetCoreMultiTenancyOptions()
public AbpAspNetCoreMultiTenancyOptions()
{
TenantKey = TenantResolverConsts.DefaultTenantKey;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class CookieTenantResolveContributor : HttpTenantResolveContributorBase

protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
return httpContext.Request?.Cookies[context.GetAspNetCoreMultiTenancyOptions().TenantKey];
return httpContext.Request?.Cookies[context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey];
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveC
return null;
}

var tenantIdKey = context.GetAspNetCoreMultiTenancyOptions().TenantKey;
var tenantIdKey = context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey;

var tenantIdHeader = httpContext.Request.Headers[tenantIdKey];
if (tenantIdHeader == string.Empty || tenantIdHeader.Count < 1)
Expand Down
Loading

0 comments on commit 1139f57

Please sign in to comment.