@ -1,74 +1,39 @@ |
|||||
## Entity Framework Core PostgreSQL integrace |
# Přepnutí na EF Core PostgreSQL providera |
||||
|
|
||||
> Podívejte se na [Entity Framework Core integrační dokument](../Entity-Framework-Core.md) pro základy integrace EF Core. |
Tento dokument vysvětluje, jak přepnout na poskytovatele databáze **PostgreSQL** pro **[spouštěcí šablonu aplikace](Startup-Templates/Application.md)**, která je dodávána s předem nakonfigurovaným SQL poskytovatelem. |
||||
|
|
||||
### Aktualizace projektu EntityFrameworkCore |
## Výměna balíku Volo.Abp.EntityFrameworkCore.SqlServer |
||||
|
|
||||
- V projektu `Acme.BookStore.EntityFrameworkCore` nahraďte balík `Volo.Abp.EntityFrameworkCore.SqlServer` za `Volo.Abp.EntityFrameworkCore.PostgreSql` |
Projekt `.EntityFrameworkCore` v řešení závisí na NuGet balíku [Volo.Abp.EntityFrameworkCore.SqlServer](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.SqlServer). Odstraňte tento balík a přidejte stejnou verzi balíku [Volo.Abp.EntityFrameworkCore.PostgreSql](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.PostgreSql). |
||||
- Aktualizace pro použití PostgreSQL v `BookStoreEntityFrameworkCoreModule` |
|
||||
- Nahraďte `AbpEntityFrameworkCoreSqlServerModule` za `AbpEntityFrameworkCorePostgreSqlModule` |
|
||||
- Nahraďte `options.UseSqlServer()` za `options.UsePostgreSql()` |
|
||||
- V jiných projektech aktualizujte PostgreSQL connection string v nezbytných `appsettings.json` souborech |
|
||||
- Více informací v [PostgreSQL connection strings](https://www.connectionstrings.com/postgresql/), v tomto dokumentu věnujte pozornost sekci `Npgsql` |
|
||||
|
|
||||
### Aktualizace projektu EntityFrameworkCore.DbMigrations |
## Nahrazení závislosti modulu |
||||
- Aktualizace pro použití PostgreSQL v `XXXMigrationsDbContextFactory` |
|
||||
- Nahraďte `new DbContextOptionsBuilder<XXXMigrationsDbContext>().UseSqlServer()` za `new DbContextOptionsBuilder<XXXMigrationsDbContext>().UseNpgsql()` |
|
||||
|
|
||||
|
Najděte třídu ***YourProjectName*EntityFrameworkCoreModule** v projektu `.EntityFrameworkCore`, odstraňte `typeof(AbpEntityFrameworkCoreSqlServerModule)` z atributu `DependsOn`, přidejte `typeof(AbpEntityFrameworkCorePostgreSqlModule)` (také nahraďte `using Volo.Abp.EntityFrameworkCore.SqlServer;` za `using Volo.Abp.EntityFrameworkCore.PostgreSql;`). |
||||
|
|
||||
### Odstranění stávajících migrací |
## UsePostgreSql() |
||||
|
|
||||
Smažte všechny stavající migrační soubory (včetně `DbContextModelSnapshot`) |
Najděte volání `UseSqlServer()` v *YourProjectName*EntityFrameworkCoreModule.cs uvnitř projektu `.EntityFrameworkCore` a nahraďte za `UsePostgreSql()`. |
||||
|
|
||||
 |
Najděte volání `UseSqlServer()` v *YourProjectName*MigrationsDbContextFactory.cs uvnitř projektu `.EntityFrameworkCore.DbMigrations` a nahraďte za `UseNpgsql()`. |
||||
|
|
||||
### Znovu vygenerujte počáteční migraci |
> V závislosti na struktuře řešení můžete najít více volání `UseSqlServer()`, které je třeba změnit. |
||||
|
|
||||
Nastavte správný spouštěcí projekt (obvykle web projekt) |
## Změna connection stringů |
||||
|
|
||||
 |
PostgreSql connection stringy se od těch pro SQL Server liší. Je proto potřeba zkontrolovat všechny soubory `appsettings.json` v řešení a connection stringy v nich nahradit. Podívejte se na [connectionstrings.com](https://www.connectionstrings.com/postgresql/) pro více detailů o možnostech PostgreSql connection stringů. |
||||
|
|
||||
Otevřete **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console), zvolte `.EntityFrameworkCore.DbMigrations` jako **Default project** a proveďte následující příkaz: |
Typicky je potřeba změnit `appsettings.json` v projektech `.DbMigrator` a `.Web` projects, ale to záleží na vaší struktuře řešení. |
||||
|
|
||||
Proveďte příkaz `Add-Migration`: |
## Regenerace migrací |
||||
```` |
|
||||
PM> Add-Migration Initial |
|
||||
```` |
|
||||
|
|
||||
### Aktualizace databáze |
Startovací šablona používá [Entity Framework Core Code First migrace](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). EF Core migrace závisí na zvoleném DBMS poskytovateli. Tudíž změna DBMS poskytovatele způsobí selhání migrace. |
||||
|
* Smažte složku Migrations v projektu `.EntityFrameworkCore.DbMigrations` and znovu sestavte řešení. |
||||
|
* Spusťte `Add-Migration "Initial"` v Package Manager Console (je nutné zvolit `.DbMigrator` (nebo `.Web`) projekt jako startovací projekt v Solution Explorer a zvolit projekt `.EntityFrameworkCore.DbMigrations` jako výchozí v Package Manager Console). |
||||
|
|
||||
K vytvoření databáze máte dvě možnosti. |
Tímto vytvoříte migraci databáze se všemi nakonfigurovanými databázovými objekty (tabulkami). |
||||
|
|
||||
#### Použití DbMigrator aplikace |
Spusťte projekt `.DbMigrator` k vytvoření databáze a vložení počátečních dat. |
||||
|
|
||||
Řešení obsahuje konzolovou aplikaci (v tomto příkladu nazvanou `Acme.BookStore.DbMigrator`), která může vytvářet databáze, aplikovat migrace a vkládat seed data. Je užitečná jak pro vývojové, tak pro produkční prostředí. |
## Spuštění aplikace |
||||
|
|
||||
> Projekt `.DbMigrator` má vlastní `appsettings.json`. Takže pokud jste změnili connection string uvedený výše, musíte změnit také tento. |
Vše je připraveno. Stačí už jen spustit aplikaci a užívat si kódování. |
||||
|
|
||||
Klikněte pravým na projekt `.DbMigrator` a vyberte **Set as StartUp Project**: |
|
||||
|
|
||||
 |
|
||||
|
|
||||
Zmáčkněte F5 (nebo Ctrl+F5) ke spuštění aplikace. Výstup bude vypadat následovně: |
|
||||
|
|
||||
 |
|
||||
|
|
||||
#### Použití EF Core Update-Database příkazu |
|
||||
|
|
||||
Ef Core má `Update-Database` příkaz, který v případě potřeby vytvoří databázi a aplikuje čekající migrace. |
|
||||
|
|
||||
Nastavte správný spouštěcí projekt (obvykle web projekt) |
|
||||
|
|
||||
 |
|
||||
|
|
||||
Otevřete **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console), vyberte projekt `.EntityFrameworkCore.DbMigrations` jako **Default Project** and spusťte následující příkaz: |
|
||||
|
|
||||
```` |
|
||||
PM> Update-Database |
|
||||
```` |
|
||||
|
|
||||
Dojde k vytvoření nové databáze na základě nakonfigurovaného connection stringu. |
|
||||
|
|
||||
 |
|
||||
|
|
||||
> Použití nástroje `.DbMigrator` je doporučený způsob, jelikož zároveň vloží seed data nutné k správnému běhu webové aplikace. |
|
||||
|
|||||
|
After Width: | Height: | Size: 9.4 KiB |
@ -0,0 +1,3 @@ |
|||||
|
## Ambient Context Pattern |
||||
|
|
||||
|
TODO |
||||
@ -1,3 +1,372 @@ |
|||||
# Audit Logging |
# Audit Logging |
||||
|
|
||||
TODO |
[Wikipedia](https://en.wikipedia.org/wiki/Audit_trail): "*An audit trail (also called **audit log**) is a security-relevant chronological record, set of records, and/or destination and source of records that provide documentary evidence of the sequence of activities that have affected at any time a specific operation, procedure, or event*". |
||||
|
|
||||
|
ABP Framework provides an **extensible audit logging system** that automates the audit logging by **convention** and provides **configuration** points to control the level of the audit logs. |
||||
|
|
||||
|
An **audit log object** (see the Audit Log Object section below) is typically created & saved per web request. It includes; |
||||
|
|
||||
|
* **Request & response details** (like URL, Http method, Browser info, HTTP status code... etc.). |
||||
|
* **Performed actions** (controller actions and application service method calls with their parameters). |
||||
|
* **Entity changes** occurred in the web request. |
||||
|
* **Exception** information (if there was an error while executing the request). |
||||
|
* **Request duration** (to measure the performance of the application). |
||||
|
|
||||
|
> [Startup templates](Startup-Templates/Index.md) are configured for the audit logging system which is suitable for most of the applications. Use this document for a detailed control over the audit log system. |
||||
|
|
||||
|
### Database Provider Support |
||||
|
|
||||
|
* Fully supported by the [Entity Framework Core](Entity-Framework-Core.md) provider. |
||||
|
* Entity change logging is not supported by the [MongoDB](MongoDB.md) provider. Other features work as expected. |
||||
|
|
||||
|
## UseAuditing() |
||||
|
|
||||
|
`UseAuditing()` middleware should be added to the ASP.NET Core request pipeline in order to create and save the audit logs. If you've created your applications using [the startup templates](Startup-Templates/Index.md), it is already added. |
||||
|
|
||||
|
## AbpAuditingOptions |
||||
|
|
||||
|
`AbpAuditingOptions` is the main [options object](Options.md) to configure the audit log system. You can configure it in the `ConfigureServices` method of your [module](Module-Development-Basics.md): |
||||
|
|
||||
|
````csharp |
||||
|
Configure<AbpAuditingOptions>(options => |
||||
|
{ |
||||
|
options.IsEnabled = false; //Disables the auditing system |
||||
|
}); |
||||
|
```` |
||||
|
|
||||
|
Here, a list of the options you can configure: |
||||
|
|
||||
|
* `IsEnabled` (default: `true`): A root switch to enable or disable the auditing system. Other options is not used if this value is `false`. |
||||
|
* `HideErrors` (default: `true`): Audit log system hides and write regular [logs](Logging.md) if any error occurs while saving the audit log objects. If saving the audit logs is critical for your system, set this to `false` to throw exception in case of hiding the errors. |
||||
|
* `IsEnabledForAnonymousUsers` (default: `true`): If you want to write audit logs only for the authenticated users, set this to `false`. If you save audit logs for anonymous users, you will see `null` for `UserId` values for these users. |
||||
|
* `IsEnabledForGetRequests` (default: `false`): HTTP GET requests should not make any change in the database normally and audit log system doesn't save audit log objects for GET request. Set this to `true` to enable it also for the GET requests. |
||||
|
* `ApplicationName`: If multiple applications saving audit logs into a single database, set this property to your application name, so you can distinguish the logs of different applications. |
||||
|
* `IgnoredTypes`: A list of `Type`s to be ignored for audit logging. If this is an entity type, changes for this type of entities will not be saved. This list is also used while serializing the action parameters. |
||||
|
* `EntityHistorySelectors`: A list of selectors those are used to determine if an entity type is selected for saving the entity change. See the section below for details. |
||||
|
* `Contributors`: A list of `AuditLogContributor` implementations. A contributor is a way of extending the audit log system. See the "Audit Log Contributors" section below. |
||||
|
|
||||
|
### Entity History Selectors |
||||
|
|
||||
|
Saving all changes of all your entities would require a lot of database space. For this reason, **audit log system doesn't save any change for the entities unless you explicitly configure it**. |
||||
|
|
||||
|
To save all changes of all entities, simply use the `AddAllEntities()` extension method. |
||||
|
|
||||
|
````csharp |
||||
|
Configure<AbpAuditingOptions>(options => |
||||
|
{ |
||||
|
options.EntityHistorySelectors.AddAllEntities(); |
||||
|
}); |
||||
|
```` |
||||
|
|
||||
|
`options.EntityHistorySelectors` actually a list of type predicate. You can write a lambda expression to define your filter. |
||||
|
|
||||
|
The example selector below does the same of the `AddAllEntities()` extension method defined above: |
||||
|
|
||||
|
````csharp |
||||
|
Configure<AbpAuditingOptions>(options => |
||||
|
{ |
||||
|
options.EntityHistorySelectors.Add( |
||||
|
new NamedTypeSelector( |
||||
|
"MySelectorName", |
||||
|
type => |
||||
|
{ |
||||
|
if (typeof(IEntity).IsAssignableFrom(type)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
); |
||||
|
}); |
||||
|
```` |
||||
|
|
||||
|
The condition `typeof(IEntity).IsAssignableFrom(type)` will be `true` for any class implements the `IEntity` interface (this is technically all the entities in your application). You can conditionally check and return `true` or `false` based on your preference. |
||||
|
|
||||
|
`options.EntityHistorySelectors` is a flexible and dynamic way of selecting the entities for audit logging. Another way is to use the `Audited` and `DisableAuditing` attributes per entity. |
||||
|
|
||||
|
## Enabling/Disabling Audit Logging for Services |
||||
|
|
||||
|
### Enable/Disable for Controllers & Actions |
||||
|
|
||||
|
All the controller actions are logged by default (see `IsEnabledForGetRequests` above for GET requests). |
||||
|
|
||||
|
You can use the `[DisableAuditing]` to disable it for a specific controller type: |
||||
|
|
||||
|
````csharp |
||||
|
[DisableAuditing] |
||||
|
public class HomeController : AbpController |
||||
|
{ |
||||
|
//... |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
Use `[DisableAuditing]` for any action to control it in the action level: |
||||
|
|
||||
|
````csharp |
||||
|
public class HomeController : AbpController |
||||
|
{ |
||||
|
[DisableAuditing] |
||||
|
public async Task<ActionResult> Home() |
||||
|
{ |
||||
|
//... |
||||
|
} |
||||
|
|
||||
|
public async Task<ActionResult> OtherActionLogged() |
||||
|
{ |
||||
|
//... |
||||
|
} |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
### Enable/Disable for Application Services & Methods |
||||
|
|
||||
|
[Application service](Application-Services.md) method calls also included into the audit log by default. You can use the `[DisableAuditing]` in service or method level. |
||||
|
|
||||
|
#### Enable/Disable for Other Services |
||||
|
|
||||
|
Action audit logging can be enabled for any type of class (registered to and resolved from the [dependency injection](Dependency-Injection.md)) while it is only enabled for the controllers and the application services by default. |
||||
|
|
||||
|
Use `[Audited]` and `[DisableAuditing]` for any class or method that need to be audit logged. In addition, your class can (directly or inherently) implement the `IAuditingEnabled` interface to enable the audit logging for that class by default. |
||||
|
|
||||
|
### Enable/Disable for Entities & Properties |
||||
|
|
||||
|
An entity is ignored on entity change audit logging in the following cases; |
||||
|
|
||||
|
* If you add an entity type to the `AbpAuditingOptions.IgnoredTypes` (as explained before), it is completely ignored in the audit logging system. |
||||
|
* If the object is not an [entity](Entities.md) (not implements `IEntity` directly or inherently - All entities implement this interface by default). |
||||
|
* If entity type is not public. |
||||
|
|
||||
|
Otherwise, you can use `Audited` to enable entity change audit logging for an entity: |
||||
|
|
||||
|
````csharp |
||||
|
[Audited] |
||||
|
public class MyEntity : Entity<Guid> |
||||
|
{ |
||||
|
//... |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
Or disable it for an entity: |
||||
|
|
||||
|
````csharp |
||||
|
[DisableAuditing] |
||||
|
public class MyEntity : Entity<Guid> |
||||
|
{ |
||||
|
//... |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
Disabling audit logging can be necessary only if the entity is being selected by the `AbpAuditingOptions.EntityHistorySelectors` that explained before. |
||||
|
|
||||
|
You can disable auditing only some properties of your entities for a detailed control over the audit logging: |
||||
|
|
||||
|
````csharp |
||||
|
[Audited] |
||||
|
public class MyUser : Entity<Guid> |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string Email { get; set; } |
||||
|
|
||||
|
[DisableAuditing] //Ignore the Passoword on audit logging |
||||
|
public string Password { get; set; } |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
Audit log system will save changes for the `MyUser` entity while it ignores the `Password` property which can be dangerous to save for security purposes. |
||||
|
|
||||
|
In some cases, you may want to save a few properties but ignore all others. Writing `[DisableAuditing]` for all the other properties would be tedious. In such cases, use `[Audited]` only for the desired properties and mark the entity with the `[DisableAuditing]` attribute: |
||||
|
|
||||
|
````csharp |
||||
|
[DisableAuditing] |
||||
|
public class MyUser : Entity<Guid> |
||||
|
{ |
||||
|
[Audited] //Only log the Name change |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string Email { get; set; } |
||||
|
|
||||
|
public string Password { get; set; } |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
## IAuditingStore |
||||
|
|
||||
|
`IAuditingStore` is an interface that is used to save the audit log objects (explained below) by the ABP Framework. If you need to save the audit log objects to a custom data store, you can implement the `IAuditingStore` in your own application and replace using the [dependency injection system](Dependency-Injection.md). |
||||
|
|
||||
|
`SimpleLogAuditingStore` is used if no audit store was registered. It simply writes the audit object to the standard [logging system](Logging.md). |
||||
|
|
||||
|
[The Audit Logging Module](Modules/Audit-Logging.md) has been configured in [the startup templates](Startup-Templates/Index.md) saves audit log objects to a database (it supports multiple database providers). So, most of the times you don't care about how `IAuditingStore` was implemented and used. |
||||
|
|
||||
|
## Audit Log Object |
||||
|
|
||||
|
An **audit log object** is created for each **web request** by default. An audit log object can be represented by the following relation diagram: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
* **AuditLogInfo**: The root object with the following properties: |
||||
|
* `ApplicationName`: When you save audit logs of different applications to the same database, this property is used to distinguish the logs of the applications. |
||||
|
* `UserId`: Id of the current user, if the user has logged in. |
||||
|
* `UserName`: User name of the current user, if the user has logged in (this value is here to not depend on the identity module/system for lookup). |
||||
|
* `TenantId`: Id of the current tenant, for a multi-tenant application. |
||||
|
* `TenantName`: Name of the current tenant, for a multi-tenant application. |
||||
|
* `ExecutionTime`: The time when this audit log object has been created. |
||||
|
* `ExecutionDuration`: Total execution duration of the request, in milliseconds. This can be used to observe the performance of the application. |
||||
|
* `ClientId`: Id of the current client, if the client has been authenticated. A client is generally a 3rd-party application using the system over an HTTP API. |
||||
|
* `ClientName`: Name of the current client, if available. |
||||
|
* `ClientIpAddress`: IP address of the client/user device. |
||||
|
* `CorrelationId`: Current [Correlation Id]((CorrelationId.md)). Correlation Id is used to relate the audit logs written by different applications (or microservices) in a single logical operation. |
||||
|
* `BrowserInfo`: Browser name/version info of the current user, if available. |
||||
|
* `HttpMethod`: HTTP method of the current request (GET, POST, PUT, DELETE... etc.). |
||||
|
* `HttpStatusCode`: HTTP response status code for this request. |
||||
|
* `Url`: URL of the request. |
||||
|
* **AuditLogActionInfo**: An audit log action is typically a controller action or an [application service](Application-Services.md) method call during the web request. One audit log may contain multiple actions. An action object has the following properties: |
||||
|
* `ServiceName`: Name of the executed controller/service. |
||||
|
* `MethodName`: Name of the executed method of the controller/service. |
||||
|
* `Parameters`: A JSON formatted text representing the parameters passed to the method. |
||||
|
* `ExecutionTime`: The time when this method was executed. |
||||
|
* `ExecutionDuration`: Duration of the method execution, in milliseconds. This can be used to observe the performance of the method. |
||||
|
* **EntityChangeInfo**: Represents a change of an entity in this web request. An audit log may contain zero or more entity changes. An entity change has the following properties: |
||||
|
* `ChangeTime`: The time when the entity was changed. |
||||
|
* `ChangeType`: An enum with the following fields: `Created` (0), `Updated` (1) and `Deleted` (2). |
||||
|
* `EntityId`: Id of the entity that was changed. |
||||
|
* `EntityTenantId`: Id of the tenant this entity belongs to. |
||||
|
* `EntityTypeFullName`: Type (class) name of the entity with full namespace (like *Acme.BookStore.Book* for the Book entity). |
||||
|
* **EntityPropertyChangeInfo**: Represents a change of a property of an entity. An entity change info (explained above) may contain one or more property change with the following properties: |
||||
|
* `NewValue`: New value of the property. It is `null` if the entity was deleted. |
||||
|
* `OriginalValue`: Old/original value before the change. It is `null` if the entity was newly created. |
||||
|
* `PropertyName`: The name of the property on the entity class. |
||||
|
* `PropertyTypeFullName`: Type (class) name of the property with full namespace. |
||||
|
* **Exception**: An audit log object may contain zero or more exception. In this way, you can get a report of the failed requests. |
||||
|
* **Comment**: An arbitrary string value to add custom messages to the audit log entry. An audit log object may contain zero or more comments. |
||||
|
|
||||
|
In addition to the standard properties explained above, `AuditLogInfo`, `AuditLogActionInfo` and `EntityChangeInfo` objects implement the `IHasExtraProperties` interface, so you can add custom properties to these objects. |
||||
|
|
||||
|
## Audit Log Contributors |
||||
|
|
||||
|
You can extend the auditing system by creating a class that is derived from the `AuditLogContributor` class which defines the `PreContribute` and the `PostContribute` methods. |
||||
|
|
||||
|
The only pre-built contributor is the `AspNetCoreAuditLogContributor` class which sets the related properties for an HTTP request. |
||||
|
|
||||
|
A contributor can set properties and collections of the `AuditLogInfo` class to add more information. |
||||
|
|
||||
|
Example: |
||||
|
|
||||
|
````csharp |
||||
|
public class MyAuditLogContributor : AuditLogContributor |
||||
|
{ |
||||
|
public override void PreContribute(AuditLogContributionContext context) |
||||
|
{ |
||||
|
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>(); |
||||
|
context.AuditInfo.SetProperty( |
||||
|
"MyCustomClaimValue", |
||||
|
currentUser.FindClaimValue("MyCustomClaim") |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public override void PostContribute(AuditLogContributionContext context) |
||||
|
{ |
||||
|
context.AuditInfo.Comments.Add("Some comment..."); |
||||
|
} |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
* `context.ServiceProvider` can be used to resolve services from the [dependency injection](Dependency-Injection.md). |
||||
|
* `context.AuditInfo` can be used to access to the current audit log object to manipulate it. |
||||
|
|
||||
|
After creating such a contributor, you must add it to the `AbpAuditingOptions.Contributors` list: |
||||
|
|
||||
|
````csharp |
||||
|
Configure<AbpAuditingOptions>(options => |
||||
|
{ |
||||
|
options.Contributors.Add(new MyAuditLogContributor()); |
||||
|
}); |
||||
|
```` |
||||
|
|
||||
|
## IAuditLogScope & IAuditingManager |
||||
|
|
||||
|
This section explains the `IAuditLogScope` & `IAuditingManager` services for advanced use cases. |
||||
|
|
||||
|
An **audit log scope** is an [ambient scope](Ambient-Context-Pattern.md) that **builds** and **saves** an audit log object (explained before). By default, an audit log scope is created for a web request by the Audit Log Middleware (see `UseAuditing()` section above). |
||||
|
|
||||
|
### Access to the Current Audit Log Scope |
||||
|
|
||||
|
Audit log contributors, was explained above, is a global way of manipulating the audit log object. It is good if you can get a value from a service. |
||||
|
|
||||
|
If you need to manipulate the audit log object in an arbitrary point of your application, you can access to the current audit log scope and get the current audit log object (independent of how the scope is managed). Example: |
||||
|
|
||||
|
````csharp |
||||
|
public class MyService : ITransientDependency |
||||
|
{ |
||||
|
private readonly IAuditingManager _auditingManager; |
||||
|
|
||||
|
public MyService(IAuditingManager auditingManager) |
||||
|
{ |
||||
|
_auditingManager = auditingManager; |
||||
|
} |
||||
|
|
||||
|
public async Task DoItAsync() |
||||
|
{ |
||||
|
var currentAuditLogScope = _auditingManager.Current; |
||||
|
if (currentAuditLogScope != null) |
||||
|
{ |
||||
|
currentAuditLogScope.Log.Comments.Add( |
||||
|
"Executed the MyService.DoItAsync method :)" |
||||
|
); |
||||
|
|
||||
|
currentAuditLogScope.Log.SetProperty("MyCustomProperty", 42); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
Always check if `_auditingManager.Current` is null or not, because it is controlled in an outer scope and you can't know if an audit log scope was created before calling your method. |
||||
|
|
||||
|
### Manually Create an Audit Log Scope |
||||
|
|
||||
|
You rarely need to create a manual audit log scope, but if you need, you can create an audit log scope using the `IAuditingManager` as like in the following example: |
||||
|
|
||||
|
````csharp |
||||
|
public class MyService : ITransientDependency |
||||
|
{ |
||||
|
private readonly IAuditingManager _auditingManager; |
||||
|
|
||||
|
public MyService(IAuditingManager auditingManager) |
||||
|
{ |
||||
|
_auditingManager = auditingManager; |
||||
|
} |
||||
|
|
||||
|
public async Task DoItAsync() |
||||
|
{ |
||||
|
using (var auditingScope = _auditingManager.BeginScope()) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
//Call other services... |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
//Add exceptions |
||||
|
_auditingManager.Current.Log.Exceptions.Add(ex); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
//Always save the log |
||||
|
await auditingScope.SaveAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
You can call other services, they may call others, they may change entities and so on. All these interactions are saved as a single audit log object in the finally block. |
||||
|
|
||||
|
## The Audit Logging Module |
||||
|
|
||||
|
The Audit Logging Module basically implements the `IAuditingStore` to save the audit log objects to a database. It supports multiple database providers. This module is added to the startup templates by default. |
||||
|
|
||||
|
See [the Audit Logging Module document](Modules/Audit-Logging.md) for more about it. |
||||
@ -1,131 +1,164 @@ |
|||||
# ABP Framework v2.0 and the ABP Commercial |
# ABP Framework v2.0 and the ABP Commercial |
||||
|
|
||||
ABP Framework v2.0 has been released in this week. This post explains why we've released an **early major version** and what is changed with the v2.0. |
ABP Framework v2.0 has been released in this week. This post explains why we have released an **early major version** and what is changed with version 2.0. |
||||
|
|
||||
In addition to the v2.0 release, we've also announcing the **ABP Commercial** which is a set of professional modules, tools, themes and services built on top of the open source ABP framework |
In addition to the v2.0 release, we are excited to announce the **ABP Commercial**, which is a set of professional modules, tools, themes, and services built on top of the open-source ABP framework. |
||||
|
|
||||
## ABP Framework v2.0 |
## ABP Framework v2.0 |
||||
|
|
||||
### Why 2.0 instead of 1.2? |
### Why 2.0 instead of 1.2? |
||||
|
|
||||
Actually, it was planned to release v1.2 after the [v1.1.2](https://github.com/abpframework/abp/releases/tag/1.1.2) release. However, [it is reported](https://github.com/abpframework/abp/issues/2026) that v1.x has some **performance** and **stability** problems on Linux, especially when you deploy your application into **Linux** containers with **low CPU and memory** resources. |
It was planned to release v1.2 after the [v1.1.2](https://github.com/abpframework/abp/releases/tag/1.1.2) release. However, [it is reported](https://github.com/abpframework/abp/issues/2026) that v1.x has some **performance** and **stability** issues on Linux, especially when you deploy your application to **Linux** containers with **low CPU and memory** resources. |
||||
|
|
||||
We have investigated the problem deeply and have seen that the root cause of the problem is related to the implementation of **intercepting async methods**. In addition, there were some **async over sync** usages effected the thread pool optimization. |
We have investigated the problem deeply and have seen that the root cause of the problem was related to the implementation of **intercepting `async` methods**. Besides, there were some **`async` over `sync`** usages that effected the thread pool optimization. |
||||
|
|
||||
Finally, we **solved all the problems** with the huge help of the **community**. But we also had some important **design decisions** which cause some **breaking changes** and we had to change the major version number of the framework because of the **semantic versioning**. |
Finally, we **solved all the problems** with the great help of the **community**. But we also had some important **design decisions** which cause some **breaking changes** and we had to change the major version number of the framework because of the [semantic versioning](https://semver.org/). |
||||
|
|
||||
Most of the applications won't be effected by [the breaking changes](https://github.com/abpframework/abp/releases), or it will be trivial to make necessary changes. |
Most of the applications won't be affected by [the breaking changes](https://github.com/abpframework/abp/releases), or it will be trivial to make these necessary changes. |
||||
|
|
||||
### Breaking Changes |
### Breaking Changes |
||||
|
|
||||
#### Removed Some Sync APIs |
#### Removed Some Sync APIs |
||||
|
|
||||
We've [removed some sync APIs](https://github.com/abpframework/abp/pull/2464) because they eventually causes async over sync problems. Because some of the interceptors need to use async APIs and if they intercept sync methods they need to call async over sync. |
Some of the interceptors are required to use `async` APIs. When they intercept `sync` methods, they need to call `async` over `sync`. This eventually ends up with `async` over `sync` problem. That's why we have [removed some sync APIs](https://github.com/abpframework/abp/pull/2464). |
||||
|
|
||||
**Async over sync** problem is a classic problem of C# when you need to **call an async method inside a sync method**. While there are some solutions to this problem, they all have **disadvantages** and it is suggested to **not write** such code at all. You can find plenty of documents related to this topic on the web, so I will not write more about it. |
**`Async` over `sync`** pattern is a classical problem of `C#` when you need to **call an `async` method inside a `sync` method**. While there are some workarounds to this problem, they all have **disadvantages** and it is suggested to **not write** such code at all. You can find many documents related to this topic on the web. |
||||
|
|
||||
So, to not cause this problem; |
To avoid this problem, we have removed: |
||||
|
|
||||
* Removed sync [Repository](https://docs.abp.io/en/abp/latest/Repositories) methods (like Insert, Update... etc). |
- `sync` [repository](https://docs.abp.io/en/abp/latest/Repositories) methods (like `insert`, `update`, etc...), |
||||
* Removed sync APIs of the [Unit Of Work](https://docs.abp.io/en/abp/latest/Unit-Of-Work). |
- `sync` APIs of the [unit of work](https://docs.abp.io/en/abp/latest/Unit-Of-Work), |
||||
* Removed sync API of the [background jobs](https://docs.abp.io/en/abp/latest/Background-Jobs). |
- `sync` APIs of the [background jobs](https://docs.abp.io/en/abp/latest/Background-Jobs), |
||||
* Removed sync APIs of [Audit logging](https://docs.abp.io/en/abp/latest/Audit-Logging). |
- `sync` APIs of the [audit logging](https://docs.abp.io/en/abp/latest/Audit-Logging), |
||||
|
- some other rarely used `sync` APIs. |
||||
|
|
||||
Also removed some other rarely used sync APIs. If you get any compile error, just use the async versions of these APIs. |
If you get any compile error, just use the `async` versions of these APIs. |
||||
|
|
||||
#### Always Async! |
#### Always Async! |
||||
|
|
||||
Beginning from the v2.0, ABP framework assumes that you are writing your application code async. Otherwise, some framework funtionalities may not properly work. |
Beginning from the v2.0, the ABP framework assumes that you are writing your application code `async` first. Otherwise, some framework functionalities may not properly work. |
||||
|
|
||||
It is suggested to write async for all your [application services](https://docs.abp.io/en/abp/latest/Application-Services), [repository methods](https://docs.abp.io/en/abp/latest/Repositories), controller actions, page handlers. |
It is suggested to write `async` to all your [application services](https://docs.abp.io/en/abp/latest/Application-Services), [repository methods](https://docs.abp.io/en/abp/latest/Repositories), controller actions, page handlers. |
||||
|
|
||||
Even if your application service method doesn't need to be async, write it as async, because interceptors perform async operations (for authorization, unit of work... etc.). You can return `Task.Completed` from a method that doesn't make an async call. |
Even if your application service method doesn't need to be `async` , set it as `async` , because interceptors perform `async` operations (for authorization, unit of work, etc...). You can return `Task.Completed` from a method that doesn't make an `async` call. |
||||
|
|
||||
Example: |
Example: |
||||
|
|
||||
````csharp |
````csharp |
||||
public Task<int> GetValueAsync() |
public Task<int> GetValueAsync() |
||||
{ |
{ |
||||
... |
//this method doesn't make any async call. |
||||
return Task.CompletedTask(42); |
return Task.CompletedTask(42); |
||||
} |
} |
||||
```` |
```` |
||||
|
|
||||
The example above doesn't need to be async because it doesn't perform an async call to any service. However, making it async helps to the ABP framework to run interceptors without async over sync calls. |
The example above normally doesn't need to be `async` because it doesn't perform an `async` call. However, making it `async` helps the ABP framework to run interceptors without `async` over sync calls. |
||||
|
|
||||
This rule doesn't force you to write every method async. This would not be good and would be tedious. It is only needed for the intercepted services (especially for [application services](https://docs.abp.io/en/abp/latest/Application-Services) and [repository methods](https://docs.abp.io/en/abp/latest/Repositories)) |
This rule doesn't force you to write every method `async` . This would not be good and would be tedious. It is only needed for the intercepted services (especially for [application services](https://docs.abp.io/en/abp/latest/Application-Services) and [repository methods](https://docs.abp.io/en/abp/latest/Repositories)) |
||||
|
|
||||
#### Other Breaking Changes |
#### Other Breaking Changes |
||||
|
|
||||
See [the release notes](https://github.com/abpframework/abp/releases/tag/2.0.0) for the other breaking changes while most of them will not effect your application code. |
See [the release notes](https://github.com/abpframework/abp/releases/tag/2.0.0) for the other breaking changes. Most of them will not affect your application code. |
||||
|
|
||||
### New Features |
### New Features |
||||
|
|
||||
This release also contains a few new features and tens of enhancements. Some of them are; |
This release also contains some new features and tens of enhancements: |
||||
|
|
||||
* [#2597](https://github.com/abpframework/abp/pull/2597) New Volo.Abp.AspNetCore.Serilog package. |
- [#2597](https://github.com/abpframework/abp/pull/2597) New `Volo.Abp.AspNetCore.Serilog` package. |
||||
* [#2526](https://github.com/abpframework/abp/issues/2526) Client side validation for the dynamic C# client proxies. |
- [#2526](https://github.com/abpframework/abp/issues/2526) Client-side validation for the dynamic `C#` client proxies. |
||||
* [#2374](https://github.com/abpframework/abp/issues/2374) Async background jobs. |
- [#2374](https://github.com/abpframework/abp/issues/2374) `Async` background jobs. |
||||
* [#265](https://github.com/abpframework/abp/issues/265) Managing the application shutdown. |
- [#265](https://github.com/abpframework/abp/issues/265) Managing the application shutdown. |
||||
* [#2472](https://github.com/abpframework/abp/issues/2472) Implemented DeviceFlowCodes and TokenCleanupService for the IdentityServer module. |
- [#2472](https://github.com/abpframework/abp/issues/2472) Implemented `DeviceFlowCodes` and `TokenCleanupService` for the `IdentityServer` module. |
||||
|
|
||||
See [the release notes](https://github.com/abpframework/abp/releases/tag/2.0.0) for the other features, enhancements and bug fixes. |
See [the release notes](https://github.com/abpframework/abp/releases/tag/2.0.0) for the complete list of features, enhancements and bug fixes. |
||||
|
|
||||
### Documentation |
### Documentation |
||||
|
|
||||
We've completed some missing documentation with the v2.0 release. In the next weeks, we will mostly focus on the basic documentation and tutorials. |
We have completed some missing documentation with the v2.0 release. In the following weeks, we will mostly focus on the documentation and tutorials. |
||||
|
|
||||
## ABP Commercial |
## ABP Commercial |
||||
|
|
||||
[ABP Commercial](https://commercial.abp.io/) is a set of professional **modules, tools, themes and services** built on top of the open source ABP framework. |
[ABP Commercial](https://commercial.abp.io/) is a set of professional **modules, tools, themes, and services** built on top of the open-source ABP framework. |
||||
|
|
||||
* It provides [professional modules](https://commercial.abp.io/modules) in addition to ABP Framework's free & [open source modules](https://docs.abp.io/en/abp/latest/Modules/Index). |
- It provides [professional modules](https://commercial.abp.io/modules) in addition to the ABP Framework's free & [open source modules](https://docs.abp.io/en/abp/latest/Modules/Index). |
||||
* It includes a beautiful [UI theme](https://commercial.abp.io/themes). |
- It includes a beautiful a [UI theme](https://commercial.abp.io/themes) with 5 different styles. |
||||
* It provides [ABP Suite](https://commercial.abp.io/tools/suite), a tool to assist your development to make you more productive. It currently can create full-stack CRUD pages in a few seconds by configuring your entity properties. More functionalities will be added by the time. |
- It provides the [ABP Suite](https://commercial.abp.io/tools/suite); A tool to assist your development to make you more productive. It currently can create full-stack CRUD pages in a few seconds by configuring your entity properties. More functionalities will be added over time. |
||||
* [Premium support](https://commercial.abp.io/support) for enterprise companies. |
- [Premium support](https://commercial.abp.io/support) for enterprise companies. |
||||
|
|
||||
In addition to these standard set of features, we will provide customer basis services. See the [commercial.abp.io](https://commercial.abp.io/) web site for other details. |
In addition to these standard set of features, we will provide customer basis services. See the [commercial.abp.io](https://commercial.abp.io/) web site for other details. |
||||
|
|
||||
### ABP Framework vs the ABP Commercial |
### ABP Framework vs the ABP Commercial |
||||
|
|
||||
The ABP Commercial **is not a paid version** of the ABP Framework. You can think it as **additional benefits** for professional companies. If you have budget, you can use it to save your time and develop your product faster. |
The ABP Commercial **is not a paid version** of the ABP Framework. You can consider it as **set of additional benefits** for professional companies. You can use it to save your time and develop your product faster. |
||||
|
|
||||
ABP Framework is open source & free and will always be like that. |
ABP Framework is **open source & free** and will always be like that! |
||||
|
|
||||
As a principle, we build the main infrastructure as open source while we sell additional pre-built application features, themes and tools. If you were following the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) & the [ASP.NET Zero](https://aspnetzero.com/) products, the main idea is similar. |
As a principle, we build the main infrastructure as open-source and sell additional pre-built application features, themes, and tools. The main idea similar to the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) & the [ASP.NET Zero](https://aspnetzero.com/) products. |
||||
|
|
||||
Buying a commercial license saves your significant time and effort and you can focus on your own business much more, you take a dedicated and high priority support. Also, in this way, you support the ABP core team since we are spending most of our time to develop, maintain and support the open source ABP Framework. |
Buying a commercial license saves your significant time and effort and you can focus on your own business, besides you get dedicated and high priority support. Also, you will be supporting the ABP core team since we are spending most of our time to develop, maintain and support the open-source ABP Framework. |
||||
|
|
||||
|
With the introduction of the ABP Commercial, now ABP becomes a platform. We call it as the **ABP.IO Platform** which consists of the open source ABP Framework and the ABP Commercial. |
||||
|
|
||||
|
### Demo |
||||
|
|
||||
|
If you are wondering how exactly looks like the ABP Commercial application startup template, you can easily [create a demo](https://commercial.abp.io/demo) and see it in action. The demo includes all the pre-built modules and the theme. |
||||
|
|
||||
|
Here, a screenshot from the IdentityServer management module UI: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
This is another screenshot from a demo application using the material design style of the theme: |
||||
|
|
||||
|
 |
||||
|
|
||||
### Pricing |
### Pricing |
||||
|
|
||||
You can build **unlimited projects/products**, sell to **unlimited customers**, host in **unlimited of servers** without any restriction. Pricing is mostly based on your **developer count**, required **support level** and **source code** access. There are three main packages; |
You can build **unlimited projects/products**, sell to **unlimited customers**, host **unlimited servers** without any restriction. Pricing is mostly based on the **developer count**, **support level** and **source code** requirement. There are three main packages; |
||||
|
|
||||
* **Team license**: Includes all the modules, themes and tools. Allows to develop your product with 3 developers. You can buy additional developer licenses. |
- **Team license**: Includes all the modules, themes and tools. Allows developing your product with up to 3 developers. You can buy additional developer licenses. |
||||
* **Business license**: Allows to download the source code of all the modules and the themes. Also, includes 5 developer licenses by default. You can buy additional developer licenses. |
- **Business license**: Allows downloading the source code of all the modules and the themes. Also, it includes 5 developer licenses by default. You can buy additional developer licenses. |
||||
* **Enterprise license**: Provides unlimited and private support in addition to the benefits of the business license. |
- **Enterprise license**: Provides unlimited and private support in addition to the benefits of the business license. |
||||
|
|
||||
See the [pricing page](https://commercial.abp.io/pricing) for details. In addition to the standard packages, we are also providing custom services and custom licensing. [Contact us](https://commercial.abp.io/contact) if you have any questions. |
See the [pricing page](https://commercial.abp.io/pricing) for details. In addition to the standard packages, we are also providing custom services and custom licensing. [Contact us](https://commercial.abp.io/contact) if you have any questions. |
||||
|
|
||||
#### License Comparison |
#### License Comparison |
||||
|
|
||||
The license price changes based on your developer count, required support level and source code access. |
The license price changes based on your developer count, support level and source-code access. |
||||
|
|
||||
##### The Source Code |
##### The Source-Code |
||||
|
|
||||
Team license doesn't include the source code of the pre-built modules & themes. It uses all these modules as NuGet & NPM packages. In this was, you can easily get new features and bug fixes by just updating the package dependencies. But you can't access their source code. So you don't have to possibility to embed a module's source code into your application and freely change the source code. |
Team license doesn't include the source-code of the pre-built modules & themes. It uses all these modules as **NuGet & NPM packages**. In this way, you can easily **get new features and bug fixes** by just updating the package dependencies. But you can't access their source-code. So you don't have the possibility to embed a module's source code into your application and freely change the source-code. |
||||
|
|
||||
Pre-built modules provides some level of customizability and extensibility and allows you to override services, UI parts and so on. We are working on to make them much more customizable and extensible. So, if you don't need to make major changes on the pre-built modules, the team license will be ideal for you; Because it is cheaper and allows you to easily get new features and bug fixes. |
Pre-built modules provide some level of **customization** and **extensibility** and allow you to override services, UI parts and so on. We are working on to make them much more customizable and extensible. If you don't need to make major changes in the pre-built modules, the team license will be ideal for you, because it is cheaper and allows you to easily get new features and bug fixes. |
||||
|
|
||||
Business and Enterprise licenses allow you to download the source code of any module or theme when you need. They also uses the same startup template with the team license, so all modules are used as NuGet and NPM packages. But in case of need, you can remove the package dependencies for a module and embed its source code into your own solution to completely customize it. In this case, upgrading the module will not be as easy as before when a new version is available. You don't have to upgrade it, surely. But if you want, you should do it yourself using some merge tool or Git branch system. |
Business and Enterprise licenses allow you to **download the source-code** of any module or the theme when you need it. They also use the same startup template with the team license, so all modules are used as `NuGet` & `NPM` packages by default. But in case of need, you can remove the package dependencies for a module and embed its source-code into your own solution to completely customize it. In this case, upgrading the module will not be as easy as before when a new version is available. You don't have to upgrade it, surely! But if you want, you should do it yourself using some merge tool or Git branch system. |
||||
|
|
||||
#### License Lifetime |
#### License Lifetime |
||||
|
|
||||
ABP Commercial license is **perpetual**, that means you can **use it forever** and continue to develop your applications. |
ABP Commercial license is **perpetual**, which means you can **use it forever** and continue to develop your applications. |
||||
|
|
||||
|
However, the following services are covered for one year: |
||||
|
|
||||
|
- Premium **support** ends after one year. You can continue to get community support. |
||||
|
- You can not get **updates** of the modules & the themes after one year. You can continue to use the last obtained version. You can even get bug fixes and enhancements for your current major version. |
||||
|
- You can use the **ABP Suite** tool for one year. |
||||
|
|
||||
|
If you want to continue to get these benefits, you can extend your license period. Renewing price is 20% less than the regular price. |
||||
|
|
||||
|
## NDC London 2020 |
||||
|
|
||||
|
Just like the [previous year](https://medium.com/volosoft/impressions-of-ndc-london-2019-f8f391bb7a9c), we are a partner of the famous software development conference: [NDC London](https://ndc-london.com/)! In the previous year, we were there with the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) & [ASP.NET Zero](https://aspnetzero.com/) theme: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
This year, we will be focusing on the **ABP.IO Platform** (The Open Source ABP Framework and the ABP Commercial). Our booth wall will be like that: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
If you attend to the conference, remember to visit our booth. We would be glad to talk about the ABP platform features, goals and software development in general. |
||||
|
|
||||
However, the following services are for one year: |
### Would you like to meet the ABP Team? |
||||
|
|
||||
* Premium **support** ends after one year. You can continue to get the community support. |
If you are in London and want to have a coffee with us, we will be available at February 1st afternoon. [@hibrahimkalkan](https://twitter.com/hibrahimkalkan) and [@ismcagdas](https://twitter.com/ismcagdas) will be there. |
||||
* You can not get **updates** of the modules & themes after one year. You can continue to use the last obtained version. You can even get bug fixes and enhancements for your current major version. |
|
||||
* You can use the ABP **Suite** tooling for one year. |
|
||||
|
|
||||
If you want to continue to get these benefits, you can extend your license period. Renewing price is 20% less than the regular price. |
Just write to info@abp.io if you want to meet :) |
||||
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 2.7 MiB |
@ -0,0 +1,7 @@ |
|||||
|
# Audit Logging Module |
||||
|
|
||||
|
The Audit Logging Module basically implements the `IAuditingStore` to save the audit log objects to a database. |
||||
|
|
||||
|
> Audit Logging module is already installed and configured for [the startup templates](../Startup-Templates/Index.md). So, most of the times you don't need to manually add this module to your application. |
||||
|
|
||||
|
See [the audit logging system](../Audit-Logging.md) document for more about the audit logging. |
||||
|
After Width: | Height: | Size: 28 KiB |
@ -0,0 +1,164 @@ |
|||||
|
# ABP框架v2.0 和 ABP商业版 |
||||
|
|
||||
|
ABP框架2.0版已经在本周公布.这篇文章解释了为什么我们发布了一个**抢先主版本**,和2.0版本中的变化. |
||||
|
|
||||
|
除了v2.0版本,我们很高兴地宣布**ABP商业版**,这是建立在开源ABP框架的之上的一套专业的模块,工具,主题和服务. |
||||
|
|
||||
|
## ABP框架V2.0 |
||||
|
|
||||
|
### 为什么2.0,而不是1.2? |
||||
|
|
||||
|
本来在[V1.1.2](https://github.com/abpframework/abp/releases/tag/1.1.2)发布后计划发布1.2版.然而,[有报告](https://github.com/abpframework/abp/issues/2026)称1.x版在Linux上有一些**性能**和**稳定性**问题,尤其是当应用程序部署在**低配CPU和内存**的**Linux**容器上. |
||||
|
|
||||
|
我们深入研究了这一问题,并已查明问题的根本原因与**拦截`async`方法**的实现有关.此外,也有一些 **`async`套`sync`** 的用法影响了线程池的优化. |
||||
|
|
||||
|
最后,在**社区**在大力协助下我们**解决了所有的问题**.但是,我们也有一些重要的**设计决策**导致了一些**破坏性变更**,因为[语义版本](https://semver.org/),我们不得不改变框架的主版号. |
||||
|
|
||||
|
大多数的应用程序不会受到[破坏性变更](https://github.com/abpframework/abp/releases)的影响,或者只需要做一些微小的修改. |
||||
|
|
||||
|
### 破坏性变更 |
||||
|
|
||||
|
#### 删除了一些同步的API |
||||
|
|
||||
|
一些拦截器需要使用`async`的API.当他们拦截`sync`方法时,他们需要调用`async`套`sync`.这最终导致了`async`套`sync`的问题.这就是为什么我们[删除了一些同步的API](https://github.com/abpframework/abp/pull/2464). |
||||
|
|
||||
|
当你需要**在`async`方法中调用`sync`方法**时, **`async`套`sync`** 这种模式是`C#`一个经典问题.虽然有一些解决方法,但是都有相应的**缺点**,并建议**不要写**这样的代码.你可以在网上找到关于这一话题的许多文档. |
||||
|
|
||||
|
为了避免这个问题,我们已经移除: |
||||
|
|
||||
|
- `sync`[仓储](https://docs.abp.io/en/abp/latest/Repositories)方法 (如`insert`, `update`, 等...), |
||||
|
- `sync`[工作单元](https://docs.abp.io/en/abp/latest/Unit-Of-Work)API, |
||||
|
- `sync`[后台作业](https://docs.abp.io/en/abp/latest/Background-Jobs)API, |
||||
|
- `sync`[审计日志](https://docs.abp.io/en/abp/latest/Audit-Logging)API, |
||||
|
- 其他一些很少使用的`sync`API. |
||||
|
|
||||
|
如果你遇到了编译错误,只需使用这些API的`async`版本. |
||||
|
|
||||
|
#### 始终async! |
||||
|
|
||||
|
从v2.0开始,ABP框架假设你以`async`方式编写你的应用程序代码.否则,一些框架的功能可能无法正常工作. |
||||
|
|
||||
|
建议你的所有[应用服务](https://docs.abp.io/en/abp/latest/Application-Services), [仓储方法](https://docs.abp.io/en/abp/latest/Repositories), 控制器动作(ontroller actions), 页面处理器(page handlers)都是`async`. |
||||
|
|
||||
|
即使你的应用服务方法并不需要是`async`,也将其设置为`async`,因为拦截器需要执行`async`操作(授权,工作单元等).你可以在不调用`async`的方法中返回`Task.Completed`. |
||||
|
|
||||
|
示例: |
||||
|
|
||||
|
````csharp |
||||
|
public Task<int> GetValueAsync() |
||||
|
{ |
||||
|
//这个方法没有任何async调用 |
||||
|
return Task.CompletedTask(42); |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
上述例子通常并不需要是`async`因为它不执行`async`调用.然而,将它设置为`async`,这样可以帮助ABP框架运行拦截器时避免出现`async`套sync的调用. |
||||
|
|
||||
|
此规则不强制你写的每一个方法都是`async`.这样并不好而且很乏味.只在拦截的服务上需要(特别是[应用服务](https://docs.abp.io/en/abp/latest/Application-Services)和[仓库方法](https://docs.abp.io/en/abp/latest/Repositories)) |
||||
|
|
||||
|
#### 其他破坏性变更 |
||||
|
|
||||
|
查看[发行说明](https://github.com/abpframework/abp/releases/tag/2.0.0)中的破坏性变更.他们中的大多数都不会影响你的应用程序代码. |
||||
|
|
||||
|
### 新功能 |
||||
|
|
||||
|
本次发布还包含一些新的功能和一堆改进: |
||||
|
|
||||
|
- [#2597](https://github.com/abpframework/abp/pull/2597) 新的`Volo.Abp.AspNetCore.Serilog`包. |
||||
|
- [#2526](https://github.com/abpframework/abp/issues/2526) `C#`客户端代理的客户端验证. |
||||
|
- [#2374](https://github.com/abpframework/abp/issues/2374) `async`后台作业. |
||||
|
- [#265](https://github.com/abpframework/abp/issues/265) 管理应用程序关闭. |
||||
|
- [#2472](https://github.com/abpframework/abp/issues/2472) `IdentityServer`模块实现`DeviceFlowCodes`和`TokenCleanupService`. |
||||
|
|
||||
|
功能,改进和BUG修复的完整列表, 请查看[发布说明](https://github.com/abpframework/abp/releases/tag/2.0.0). |
||||
|
|
||||
|
### 文档 |
||||
|
|
||||
|
随着v2.0的发布,我们也完成了一些缺少的文档.在接下来的几周内,我们将主要关注文档和教程. |
||||
|
|
||||
|
## ABP商业版 |
||||
|
|
||||
|
[ABP商业版](https://commercial.abp.io/)是建立在开源ABP框架之上的一套专业的**模块,工具,主题和服务**. |
||||
|
|
||||
|
- 除了ABP框架免费和[开源模块](https://docs.abp.io/en/abp/latest/Modules/Index)之外, 提供[专业模块](https://commercial.abp.io/modules). |
||||
|
- 包含一个漂亮的[UI主题](https://commercial.abp.io/themes), 具有5种不同的样式. |
||||
|
- 提供[ABP套件](https://commercial.abp.io/tools/suite); 一个让开发更具有生产力的工具. 通过配置实体属性, 它可以在几秒内创建全栈的CRUD页面. 更多的功能陆续开发中. |
||||
|
- 为企业提供[高级支持](ttps://commercial.abp.io/support). |
||||
|
|
||||
|
除了这些标准的功能,我们会将提供定制服务.更多细节请参见[commercial.abp.io](https://commercial.abp.io/)网站. |
||||
|
|
||||
|
### ABP框架 vs ABP商业版 |
||||
|
|
||||
|
ABP商业版**不是付费版本**的ABP框架.可以把它当作为专业公司提供的**附加套餐**.你可以用它来节省时间和更快地开发产品. |
||||
|
|
||||
|
ABP框架将永远是**开源免费**的! |
||||
|
|
||||
|
一个原则是,我们创建的主要基础设施作为开源产品, 然后销售额外的预制应用程序功能,主题和工具.类似于[ASP.NET Boilerplate](https://aspnetboilerplate.com/)和[ASP.NET Zero](https://aspnetzero.com/)产品. |
||||
|
|
||||
|
购买商业版许可极大地节省你的时间和精力,你可以专注于自己的业务,此外也可获得专门的和优先的支持.同时,你也在支持ABP核心团队,因为我们花了大部分时间来开发,维护和支持开源的ABP框架. |
||||
|
|
||||
|
有了ABP商业版,ABP现在变为一个平台.我们称之为**ABP.IO平台**, 其中包括开源ABP框架和ABP商业版. |
||||
|
|
||||
|
### 演示 |
||||
|
|
||||
|
如果你想知道ABP商业版应用程序的启动模板是什么样,你可以很容易地[创建一个演示](https://commercial.abp.io/demo),并看到它的实际效果.该演示包括所有的预制模块和主题. |
||||
|
|
||||
|
下面是一张IdentityServer管理模块UI的截图: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
这是一张来自使用material设计风格主题的演示应用程序的截图: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
### 价格 |
||||
|
|
||||
|
你可以创建**无限个工程/产品**, 销售给**无限个客户**, 部署在**无限台服务器上**, 不受任何限制. 定价主要是基于**开发人员个数**,**支持等级**和**源代码**需求上.有三个标准包; |
||||
|
|
||||
|
- **团队许可**: 包括所有的模块,主题和工具.允许最多3个开发者开发产品.可购买额外的开发者许可. |
||||
|
- **商业许可**: 允许下载所有的模块和主题的源代码.此外,默认包含了5个开发者许可.可购买额外的开发者许可. |
||||
|
- **企业许可**: 在商业许可上, 提供无限的专属支持. |
||||
|
|
||||
|
请查看[价格页面](https://commercial.abp.io/pricing)了解详细信息.除了标准包以外,我们也提供定制服务和定制许可.如有任何问题,请[联系我们](https://commercial.abp.io/contact). |
||||
|
|
||||
|
#### 许可比较 |
||||
|
|
||||
|
许可价格是根据开发者数量,支持等级和源代码访问而变化的. |
||||
|
|
||||
|
##### 源代码 |
||||
|
|
||||
|
团队许可证不包括预制模块和主题的源代码.以**NuGet和NPM包**的方式使用所有这些模块.通过这种方式,你可以很容易地通过更新包的依赖得到**新功能和bug修复**仅.但是不能访问其源代码.所以不能嵌入模块的源代码到你的应用程序里,和随意修改源代码. |
||||
|
|
||||
|
预制模块提供一定等级的**定制**和**扩展**,并允许你覆盖服务,UI部分等.我们正在努力使他们更加可定制和可扩展.如果你无需在预制模块中做很大修改的话,团队许可是你理想的选择,因为它更便宜,并且可轻松获得新的功能和bug修复. |
||||
|
|
||||
|
商业和企业许可允许你在需要时**下载任何模块和主题的源代码**.它们使用与团队许可相同的启动模板,所以所有的模块都默认使用`NuGet`和`NPM`包.但是,在需要的情况下,你可以从一个模块中删除包的依赖,并嵌入它的源代码到你自己的解决方案中,然后完全定制它.在这种情况下,当一个新版本可用时, 升级模块将不会那么容易.当然, 你不必升级!但是,如果你愿意,你也可以使用一些合并工具或Git的分支系统来做到这一点. |
||||
|
|
||||
|
#### 许可周期 |
||||
|
|
||||
|
ABP商业版许可是**永久的**,这意味着你可以**永远使用**它继续开发应用程序. |
||||
|
|
||||
|
但是,下面的服务周期为一年: |
||||
|
|
||||
|
- 高级**支持**一年后结束.你可以继续得到社区支持. |
||||
|
- 一年后将不会得到模块和主题的**更新**.你可以继续使用最后获得的版本.甚至可以在主版本内得到BUG修复和改进. |
||||
|
- 你可使用**ABP套件**一年. |
||||
|
|
||||
|
如果想继续获得这些好处,可延长许可期限.续订价格比正常价格低20%. |
||||
|
|
||||
|
## NDC London 2020 |
||||
|
|
||||
|
与[去年](https://medium.com/volosoft/impressions-of-ndc-london-2019-f8f391bb7a9c)一样, 我们是著名的软件开发会议[NDC London](https://ndc-london.com/)的合作伙伴! 去年, 我们开展了[ASP.NET Boilerplate](https://aspnetboilerplate.com/)和[ASP.NET Zero](https://aspnetzero.com/)主题: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
今年,我们将着重于**ABP.IO平台**(开源ABP框架和ABP商业版).我们的展位会是这样的: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
如果你参加会议,记得要参观我们的展位.我们将很高兴来谈一谈ABP平台的功能,目标和软件开发. |
||||
|
|
||||
|
### 你想见ABP团队吗? |
||||
|
|
||||
|
如果你在伦敦, 而且想和我们喝杯咖啡的话, 在2月1日的下午[@hibrahimkalkan](https://twitter.com/hibrahimkalkan)和[@ismcagdas](https://twitter.com/ismcagdas)会在那. |
||||
|
|
||||
|
想见面就给info@abp.io写个邮件 :) |
||||
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 2.7 MiB |
@ -1,3 +1,59 @@ |
|||||
# FluentValidation 集成 |
# FluentValidation 集成 |
||||
|
|
||||
TODO |
ABP[验证](Validation.md)基础设施是可扩展的. [Volo.Abp.FluentValidation](https://www.nuget.org/packages/Volo.Abp.FluentValidation) NuGet 包扩展了验证系统使其与[FluentValidation](https://fluentvalidation.net/)库一起工作. |
||||
|
|
||||
|
## 安装 |
||||
|
|
||||
|
建议使用[ABP CLI](CLI.md)安装包. |
||||
|
|
||||
|
### 使用ABP CLI |
||||
|
|
||||
|
在项目(.csproj文件)的文件夹中打开命令行窗口并输入以下命令: |
||||
|
|
||||
|
````bash |
||||
|
abp add-package Volo.Abp.FluentValidation |
||||
|
```` |
||||
|
|
||||
|
### 手动安装 |
||||
|
|
||||
|
如果你想手动安装; |
||||
|
|
||||
|
1. 添加 [Volo.Abp.FluentValidation](https://www.nuget.org/packages/Volo.Abp.FluentValidation) NuGet包到你的项目: |
||||
|
|
||||
|
```` |
||||
|
Install-Package Volo.Abp.FluentValidation |
||||
|
```` |
||||
|
|
||||
|
2. 添加 `AbpFluentValidationModule` 到你的模块的依赖列表: |
||||
|
|
||||
|
````csharp |
||||
|
[DependsOn( |
||||
|
//...other dependencies |
||||
|
typeof(AbpFluentValidationModule) //Add the FluentValidation module |
||||
|
)] |
||||
|
public class YourModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
## 使用 FluentValidation |
||||
|
|
||||
|
按照 [FluentValidation文档](https://fluentvalidation.net/) 创建验证器类. |
||||
|
例如: |
||||
|
|
||||
|
````csharp |
||||
|
public class CreateUpdateBookDtoValidator : AbstractValidator<CreateUpdateBookDto> |
||||
|
{ |
||||
|
public CreateUpdateBookDtoValidator() |
||||
|
{ |
||||
|
RuleFor(x => x.Name).Length(3, 10); |
||||
|
RuleFor(x => x.Price).ExclusiveBetween(0.0f, 999.0f); |
||||
|
} |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
ABP会自动找到这个类并在对象验证时与 `CreateUpdateBookDto` 关联. |
||||
|
|
||||
|
## 另请参阅 |
||||
|
|
||||
|
* [验证系统](Validation.md) |
||||
@ -0,0 +1,24 @@ |
|||||
|
{ |
||||
|
"culture": "cs", |
||||
|
"texts": { |
||||
|
"DisplayName:Abp.Mailing.DefaultFromAddress": "Výchozí adresa odesílatele", |
||||
|
"DisplayName:Abp.Mailing.DefaultFromDisplayName": "Výchozí zobrazované jméno odesilátele", |
||||
|
"DisplayName:Abp.Mailing.Smtp.Host": "Hostitel", |
||||
|
"DisplayName:Abp.Mailing.Smtp.Port": "Port", |
||||
|
"DisplayName:Abp.Mailing.Smtp.UserName": "Uživatelské jméno", |
||||
|
"DisplayName:Abp.Mailing.Smtp.Password": "Heslo", |
||||
|
"DisplayName:Abp.Mailing.Smtp.Domain": "Doména", |
||||
|
"DisplayName:Abp.Mailing.Smtp.EnableSsl": "Povolit SSL", |
||||
|
"DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Použít výchozí přihlašovací údaje", |
||||
|
"Description:Abp.Mailing.DefaultFromAddress": "Výchozí adresa odesílatele", |
||||
|
"Description:Abp.Mailing.DefaultFromDisplayName": "Výchozí zobrazované jméno odesilátele", |
||||
|
"Description:Abp.Mailing.Smtp.Host": "Název nebo IP adresa hostitele použitého pro SMTP transakce.", |
||||
|
"Description:Abp.Mailing.Smtp.Port": "Port použitý pro SMTP tansakce", |
||||
|
"Description:Abp.Mailing.Smtp.UserName": "Uživatelské jméno spojené s přihlašovacími údaji.", |
||||
|
"Description:Abp.Mailing.Smtp.Password": "Heslo pro uživatelské jméno spojené s přihlašovacími údaji.", |
||||
|
"Description:Abp.Mailing.Smtp.Domain": "Název domény nebo počítače, který ověřuje přihlašovací údaje.", |
||||
|
"Description:Abp.Mailing.Smtp.EnableSsl": "Zda SmtpClient používá SSL k šifrování připojení.", |
||||
|
"Description:Abp.Mailing.Smtp.UseDefaultCredentials": "Zda jsou výchozí přihlašovací údaje odesílány s požadavky." |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"culture": "cs", |
||||
|
"texts": { |
||||
|
"DisplayName:Abp.Localization.DefaultLanguage": "Výchozí jazyk", |
||||
|
"Description:Abp.Localization.DefaultLanguage": "Váchozí jazyk aplikace." |
||||
|
} |
||||
|
} |
||||