Skip to content

Commit

Permalink
Merge branch 'release/3.56.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
akak1977 committed May 13, 2021
2 parents 4bdac40 + 35c75b8 commit 80b647b
Show file tree
Hide file tree
Showing 63 changed files with 1,132 additions and 542 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</PropertyGroup>

<PropertyGroup>
<VersionPrefix>3.55.0</VersionPrefix>
<VersionPrefix>3.56.0</VersionPrefix>
<VersionSuffix></VersionSuffix>
<VersionSuffix Condition=" '$(VersionSuffix)' != '' AND '$(BuildNumber)' != '' ">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>
<NoWarn>$(NoWarn);S3875;S4457</NoWarn>
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The main principle is to help the development team to focus on the implementatio
1. *Reliability* - Can leverage a solution deployed across multiple data centers and availability zones to maximize up-time and reduce potential revenue losses.
* **HEADLESS** – Allows an enterprise to support omnichannel journeys across traditional and digital touchpoints as well as new business models.
* **EXTENSIBILITY** – The API model, persistence model, business logic can be extended as needed without deploying and re-deploying solution. This provides superior business agility and keeps up to date.
*

## Architecture Overview
The following diagram illustrates the high-level architecture and main areas of Virto Commerce solutions:

Expand Down
25 changes: 23 additions & 2 deletions VirtoCommerce.Platform.sln
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtoCommerce.Platform.Hang
EndProject
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{74EADA4F-F378-490E-8EA6-AFC5605368EA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.Platform.Web.Tests", "tests\VirtoCommerce.Platform.Web.Tests\VirtoCommerce.Platform.Web.Tests.csproj", "{11BBA3A5-5C5B-447D-9844-6ED7DDF1B961}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtoCommerce.Platform.Web.Tests", "tests\VirtoCommerce.Platform.Web.Tests\VirtoCommerce.Platform.Web.Tests.csproj", "{11BBA3A5-5C5B-447D-9844-6ED7DDF1B961}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.Platform.Core.Tests", "tests\VirtoCommerce.Platform.Core.Tests\VirtoCommerce.Platform.Core.Tests.csproj", "{1BFCF9CE-E244-4F58-BB02-F3740B0E250A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtoCommerce.Platform.Core.Tests", "tests\VirtoCommerce.Platform.Core.Tests\VirtoCommerce.Platform.Core.Tests.csproj", "{1BFCF9CE-E244-4F58-BB02-F3740B0E250A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtoCommerce.Platform.DistributedLock", "src\VirtoCommerce.Platform.DistributedLock\VirtoCommerce.Platform.DistributedLock.csproj", "{CE69328B-42DA-4F6B-9A0C-9B7F2DD9F96F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.Platform.Assets.AzureBlobStorage.Tests", "tests\VirtoCommerce.Platform.Assets.AzureBlobStorage.Tests\VirtoCommerce.Platform.Assets.AzureBlobStorage.Tests.csproj", "{707A1D34-5E3A-4655-90BB-C70DFA545476}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.Platform.Assets.FileSystem.Tests", "tests\VirtoCommerce.Platform.Assets.FileSystem.Tests\VirtoCommerce.Platform.Assets.FileSystem.Tests.csproj", "{1ECD0D01-CBE5-4092-BEF0-85ECF663560F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.Platform.Caching.Tests", "tests\VirtoCommerce.Platform.Caching.Tests\VirtoCommerce.Platform.Caching.Tests.csproj", "{AFC4524D-41C0-4DE0-B2E1-576B6205E5B0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -101,6 +107,18 @@ Global
{CE69328B-42DA-4F6B-9A0C-9B7F2DD9F96F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CE69328B-42DA-4F6B-9A0C-9B7F2DD9F96F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CE69328B-42DA-4F6B-9A0C-9B7F2DD9F96F}.Release|Any CPU.Build.0 = Release|Any CPU
{707A1D34-5E3A-4655-90BB-C70DFA545476}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{707A1D34-5E3A-4655-90BB-C70DFA545476}.Debug|Any CPU.Build.0 = Debug|Any CPU
{707A1D34-5E3A-4655-90BB-C70DFA545476}.Release|Any CPU.ActiveCfg = Release|Any CPU
{707A1D34-5E3A-4655-90BB-C70DFA545476}.Release|Any CPU.Build.0 = Release|Any CPU
{1ECD0D01-CBE5-4092-BEF0-85ECF663560F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1ECD0D01-CBE5-4092-BEF0-85ECF663560F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1ECD0D01-CBE5-4092-BEF0-85ECF663560F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1ECD0D01-CBE5-4092-BEF0-85ECF663560F}.Release|Any CPU.Build.0 = Release|Any CPU
{AFC4524D-41C0-4DE0-B2E1-576B6205E5B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFC4524D-41C0-4DE0-B2E1-576B6205E5B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFC4524D-41C0-4DE0-B2E1-576B6205E5B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AFC4524D-41C0-4DE0-B2E1-576B6205E5B0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -120,6 +138,9 @@ Global
{11BBA3A5-5C5B-447D-9844-6ED7DDF1B961} = {E70533FE-7220-4D52-9131-4EBBD10B7759}
{1BFCF9CE-E244-4F58-BB02-F3740B0E250A} = {E70533FE-7220-4D52-9131-4EBBD10B7759}
{CE69328B-42DA-4F6B-9A0C-9B7F2DD9F96F} = {90F6E3EE-475A-4844-A4C4-078613591F81}
{707A1D34-5E3A-4655-90BB-C70DFA545476} = {E70533FE-7220-4D52-9131-4EBBD10B7759}
{1ECD0D01-CBE5-4092-BEF0-85ECF663560F} = {E70533FE-7220-4D52-9131-4EBBD10B7759}
{AFC4524D-41C0-4DE0-B2E1-576B6205E5B0} = {E70533FE-7220-4D52-9131-4EBBD10B7759}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {01A94F38-27D1-412F-A4F4-F00991D1157C}
Expand Down
5 changes: 5 additions & 0 deletions docs/fundamentals/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
arrange:
- architecture-reference.md
- extensibility
- scalability.md
- ...
44 changes: 0 additions & 44 deletions docs/fundamentals/extensibility-basics.md

This file was deleted.

5 changes: 4 additions & 1 deletion docs/fundamentals/extensibility/.pages
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
arrange:
- overview.md
- extending-domain-models.md
- extending-using-events.md
- style-guide.md
- extending-main-menu.md
- blades-and-navigation.md
- metaform.md
- widgets.md
- ...
- ...
80 changes: 1 addition & 79 deletions docs/fundamentals/extensibility/extending-domain-models.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


VirtoCommerce supports extension of managed code domain types. This article shows how to use the various techniques to extend exist domain type without direct code modification.


Expand Down Expand Up @@ -165,27 +165,6 @@ Also is so important to register our new persistent schema representation `Custo
}
```

## The known problems with updating when you have a schema of persistent layer extensions.

As a background, a huge limitation of the persistent layer extension technique is the mandatory creation of an empty database migration after each derived module update that has a new migration with schema changes. Without this, you will receive this error

*The model backing the context has changed since the database was created*” each time when you will update an extendable module that has a persistent schema change and contains a new migration.

The following diagram illustrates the problem described above.
![image|657x290](../../media/extensibility-basics-2.png)

Unfortunately, there is only one solution to solve this issue, before each update of the extendable module that contains the DB schema changes it is mandatory to do the following steps with your module:

* Update to the latest version all NuGet dependencies containing the base `DbContext` class which your custom `DbContext` is derived. Usually, this project has suffix Data. E.g `VirtoCommerce.CustomerOrder.Data`.
* Generate a new “empty” migration by this command
```Console
Add-Migration BumpVersionEmptyMigration -Context {{ full type name with namespace of your DbContext }} -Verbose -OutputDir Migrations -Project {{ your module project name }} -Debug
```

* Manually edit resulting migration file, delete all generated content and left only empty migration. It is mandatory step because the resulting migration will contain the same changes as original migration in the extendable module.

* Update the module dependency version in `module.manifest file` of your custom module to point to the actual version of dependency.

## How the API understands/deserializes the derived domain types

In the previous paragraphs, we have considered extending domain types and persistent layers, but, in some cases, it is not enough. Especially when your domain types are used as DTOs (Data Transfer Objects) in public API contracts and can be used as a result or parameter in the API endpoints.
Expand All @@ -195,60 +174,3 @@ There is a technical task of an instantiation of the right “effective” type
There are two ways to force ASP.NET Core API Json serializer to understand our domain extensions:
1. Use platform-defined `PolymorphJsonConverter`. It's preferable to use in most cases. The `PolymorphJsonConverter` transparently deserializes extended domain types with no developer effort.
2. Custom JSON converter passed to MvcNewtonsoftJsonOptions. Consider using it, if `PolymorphJsonConverter` is not suitable for your specific case.

### Universal `PolymorphJsonConverter`
The `PolymorphJsonConverter` uses `AbstractTypeFactory<>` to construct instances during deserialization. There are following cases of overriding/extending, when `PolymorphJsonConverter` fits:

1. Full type override. It's the case when the derived type replaces the original type thru the call to `AbstractTypeFactory<>.OverrideType`, and the API uses the original type as a formal definition. No developer actions needed in that case. `PolymorphJsonConverter` will deserialize instances of the derived type.
1. Extending types controlled by registration thru the call to `AbstractTypeFactory<>.RegisterType`, and the API uses the basic type as a formal definition. `PolymorphJsonConverter` will construct instances of derived types by looking at the value of discriminator property (formally defined in basic type) that stores the type name of the descendant. Because the discriminator property defined in the base class, there are 2 subcases:
* The basic type was defined in the Platform or another module and the discriminator already registered as needed. No additional developer actions needed to support the deserialization of extending types.
* The basic type resides in the newly created custom module. In that case, the developer needs to tell `PolymorphJsonConverter` which of the basic type properties stores the discriminator thru the call of static method `PolymorphJsonConverter.RegisterTypeForDiscriminator` in module's `PostInitialize`.
For example, check VC Customer module: *`VirtoCommerce.CustomerModule.Web\Module.cs `*
```C#
public class Module : IModule, IExportSupport, IImportSupport
{
...
public void PostInitialize(IApplicationBuilder appBuilder)
{
...
AbstractTypeFactory<Member>.RegisterType<Organization>().MapToType<OrganizationEntity>();
AbstractTypeFactory<Member>.RegisterType<Contact>().MapToType<ContactEntity>();
AbstractTypeFactory<Member>.RegisterType<Vendor>().MapToType<VendorEntity>();
AbstractTypeFactory<Member>.RegisterType<Employee>().MapToType<EmployeeEntity>();
...
PolymorphJsonConverter.RegisterTypeForDiscriminator(typeof(Member), nameof(Member.MemberType));
...
}
...
}
```

### Custom JSON-converter

Of course, you can use the standard converters extension technique by registering custom converter in `MvcNewtonsoftJsonOptions` in module `PostInitialize`:

```C#
public class YourCustomJsonConverter : JsonConverter
{
...
...
}
```

*`/Module.cs`*
```C#
public class Module : IModule
{
public void PostInitialize(IApplicationBuilder appBuilder)
{
...

// enable polymorphic types in API controller methods
var mvcJsonOptions = appBuilder.ApplicationServices.GetService<IOptions<MvcNewtonsoftJsonOptions>>();
mvcJsonOptions.Value.SerializerSettings.Converters.Add(appBuilder.ApplicationServices.GetService<YourCustomJsonConverter>());

...

}
}
```
Loading

0 comments on commit 80b647b

Please sign in to comment.