Upgrade from Commerce 14 to 15
Steps for upgrading from Optimizely Commerce Connect 14 to Commerce Connect 15.
This article assists developers and implementers in upgrading their Optimizely Commerce Connect solutions from version 14 to Commerce Connect 15. It outlines the upgrade strategy, including the coordinated CMS 13 upgrade, breaking change resolution, and testing.
For the full list of Commerce 15 breaking changes, see Breaking changes in Commerce 15. For CMS 13 platform changes, see CMS 13 breaking changes.
ImportantCommerce 15 requires CMS 13.0.0. Upgrading to Commerce 15 means upgrading your CMS packages to version 13 at the same time. Review both the Commerce 15 and CMS 13 breaking changes before starting.
If you are upgrading from a version earlier than Commerce 14, you must first upgrade to Commerce 14 and run all migration steps before upgrading to Commerce 15. The migration steps
MigrateAdminsRoleStep,PopulateUserPermissionStep, andUpdateContactUserIdStephave been removed in Commerce 15.
Prerequisites
- Existing Commerce 14 solution – Your application should already be running on Optimizely Commerce Connect 14.
- .NET 10 SDK – Commerce 15 requires .NET 10. Packages will fail
dotnet restoreon earlier .NET versions. - Database backup – Create a full backup of your Commerce and CMS databases before starting.
- IDE – Visual Studio 2022 (17.13+) or a compatible IDE with .NET 10 support.
Pre-upgrade: Audit and prepare
Before changing any packages or code, audit your solution for potential compatibility issues.
- Review compiler warnings – Address existing deprecation warnings in your Commerce 14 build. Many Commerce 14 deprecation warnings indicate APIs removed in Commerce 15. Fixing these before upgrading significantly reduces the number of compilation errors you encounter.
- Inventory third-party packages – Check each non-Optimizely NuGet package for Commerce 15 and CMS 13 compatibility. Remove or replace incompatible packages before upgrading Optimizely packages.
- Document customizations – Note custom order processing workflows, payment implementations, catalog extensions, and integration points that may need updates.
- Identify workflow usage – If your implementation uses the legacy
Mediachase.Commerce.Workflowsystem orActivityFlowinfrastructure, plan for migration to processor-based APIs. This is typically the largest area of effort. - Identify credit card storage – If your implementation stores credit card data using
ICreditCardPaymentor theCreditCardclass, plan for migration to tokenized payment through a third-party provider. - Check for Newtonsoft.Json dependencies – Identify custom JSON converters or code that depends on
Newtonsoft.Jsontypes. Commerce 15 and CMS 13 have migrated toSystem.Text.Json.
ImportantRemoved features If your site uses the legacy workflow engine, credit card data storage, or the legacy discount classes (
Mediachase.Commerce.Orders.Discount), be aware that these features are fully removed in Commerce 15 and must be replaced before upgrading.
Step 1: Update target framework
Update your .csproj files to target .NET 10:
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>Update your global.json:
{
"sdk": {
"version": "10.0.100"
}
}If you use Docker, update your base images to .NET 10 as well.
Step 2: Update NuGet packages
Update all EPiServer.* and Optimizely.* packages to their Commerce 15 and CMS 13 versions. Key packages:
<PackageReference Include="EPiServer.Commerce.Core" Version="15.0.0" />
<PackageReference Include="EPiServer.CMS.Core" Version="13.0.0" />
<PackageReference Include="EPiServer.CMS.UI" Version="13.0.0" />
<PackageReference Include="EPiServer.CMS.UI.AspNetIdentity" Version="13.0.0" />After updating, run dotnet restore to verify all packages resolve correctly.
Remove the following packages if they are explicitly referenced, as they have been removed or consolidated:
Newtonsoft.Json– No longer a transitive dependency. Add it back explicitly only if your own code requires it.Mediachase.Commerce.Workflow– The assembly no longer exists.- Any references to removed legacy projects (
Mediachase.BusinessFoundation,WebConsoleLib,Mediachase.FileUploader).
Step 3: Migrate from Newtonsoft.Json to System.Text.Json
Commerce 15 and CMS 13 have migrated entirely to System.Text.Json. If your implementation has custom JSON converters, rewrite them:
// Before (Commerce 14) - Newtonsoft.Json
using Newtonsoft.Json;
public class MyConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(MyType);
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
// ...
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
// ...
}
}
// After (Commerce 15) - System.Text.Json
using System.Text.Json;
using System.Text.Json.Serialization;
public class MyConverter : JsonConverter<MyType>
{
public override MyType Read(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
// ...
}
public override void Write(Utf8JsonWriter writer, MyType value,
JsonSerializerOptions options)
{
// ...
}
}If your code uses Newtonsoft.Json for non-Commerce purposes (for example, third-party API integrations), add an explicit package reference. It is no longer included as a transitive dependency.
Step 4: Migrate workflow-based order processing
If your implementation uses OrderGroup.RunWorkflow(), OrderGroupWorkflowManager, or custom ActivityFlow implementations, migrate to the processor-based APIs.
// Before (Commerce 14) - Workflow-based checkout
cart.RunWorkflow(OrderGroupWorkflowManager.CartCheckOutWorkflowName);
// After (Commerce 15) - Processor-based checkout
var validationIssues = cart.ValidateOrder();
if (!validationIssues.Any())
{
var orderReference = _orderRepository.SaveAsPurchaseOrder(cart);
var purchaseOrder = _orderRepository.Load<IPurchaseOrder>(orderReference.OrderGroupId);
// Process payments
foreach (var payment in purchaseOrder.GetFirstForm().Payments)
{
_paymentProcessor.ProcessPayment(purchaseOrder, payment, shipment);
}
// Calculate totals
var totals = _orderGroupCalculator.GetOrderGroupTotals(purchaseOrder);
_orderRepository.Save(purchaseOrder);
}Replace order status operations:
// Before (Commerce 14) - Workflow-based status changes
OrderStatusManager.CompleteOrderShipment(shipment);
OrderStatusManager.CancelOrder(purchaseOrder);
// After (Commerce 15) - Processor-based status changes
_shipmentProcessor.Complete(purchaseOrder, shipment);
_purchaseOrderProcessor.Cancel(purchaseOrder);For the full list of removed workflow methods and their replacements, see Order and payment processing breaking changes.
Step 5: Migrate credit card storage
If your implementation stores credit card data, migrate to tokenized payment through a third-party provider:
// Before (Commerce 14) - Storing credit card data
var payment = orderGroup.CreatePayment<ICreditCardPayment>();
payment.CreditCardNumber = "4111111111111111";
payment.ExpirationMonth = 12;
payment.ExpirationYear = 2025;
// After (Commerce 15) - Tokenized payment
var payment = orderGroup.CreatePayment();
payment.PaymentMethodId = paymentMethodId;
payment.Amount = orderTotal;
payment.Properties["PaymentToken"] = "tok_visa_4242";
payment.Properties["ProviderTransactionId"] = "pi_3abc123";See Customer and credit card breaking changes for the complete list of removed APIs.
Step 6: Fix remaining API breaking changes
After the major migrations above, resolve remaining compilation errors. The most common changes are listed below. For the complete list, see Breaking changes in Commerce 15.
IOrderGroup.Market removal
// Before (Commerce 14)
var market = orderGroup.Market;
// After (Commerce 15)
var market = _marketService.GetMarket(orderGroup.MarketId);Legacy discount classes removal
Replace usage of Mediachase.Commerce.Orders.Discount and its subclasses with the promotion engine:
// Before (Commerce 14)
var discounts = orderForm.Discounts; // OrderFormDiscountCollection
// After (Commerce 15)
var promotions = orderForm.Promotions; // Use IPromotionEngine for applying discounts
var discountTotal = orderForm.GetDiscountTotal();ICatalogSystem DTO methods removal
// Before (Commerce 14)
var entries = _catalogSystem.GetCatalogEntriesDto(catalogName,
parentNodeId, responseGroup);
// After (Commerce 15)
var entries = _contentLoader.GetChildren<EntryContentBase>(parentNodeReference);OrderSearchFilter.MarketId removal
// Before (Commerce 14)
var filter = new OrderSearchFilter { MarketId = "US" };
// After (Commerce 15)
var filter = new OrderSearchFilter { MarketIds = new[] { "US" } };CookieHelper removal
// Before (Commerce 14)
CookieHelper.SetCookie("key", "value");
// After (Commerce 15) - Use ASP.NET Core cookie APIs via DI
_httpContextAccessor.HttpContext?.Response.Cookies.Append("key", "value");SiteDefinition to Application model
This change comes from CMS 13. Replace ISiteDefinitionResolver with IApplicationResolver:
// Before (Commerce 14 / CMS 12)
using EPiServer.Web;
var site = _siteDefinitionResolver.GetByContent(contentLink, fallbackToWildcard: true);
// After (Commerce 15 / CMS 13)
using EPiServer.Applications;
var application = _applicationResolver.Resolve(contentLink);Constructor changes
Several classes have had obsolete constructor overloads removed. The compiler will indicate which parameters are missing. Common cases:
| Class | Required new parameter |
|---|---|
SiteContext | IHttpContextAccessor |
DefaultSiteContext | ICurrentMarket, IWebHostEnvironment, IHttpContextAccessor |
CatalogLogger | IPrincipalAccessor, IHttpContextAccessor |
ThumbnailUrlResolver | ReferenceConverter |
CatalogBuilder | CatalogMetaObjectRepository |
OrderValidationService | OrderOptions |
SeoAddressResolver | SeoUriContentReferenceResolver |
CatalogItemAssetImportExport | IAssetUrlResolver |
Step 7: Adopt async order APIs (optional)
Commerce 15 introduces async versions of all IOrderRepository methods. While not required for the upgrade, new code should prefer the async versions:
// Synchronous (still works)
var cart = _orderRepository.Load<ICart>(orderGroupId);
_orderRepository.Save(cart);
// Async (recommended for new code)
var cart = await _orderRepository.LoadAsync<ICart>(orderGroupId, cancellationToken);
await _orderRepository.SaveAsync(cart, cancellationToken);Step 8: Test and stabilize
After completing the code migration:
- Resolve all compilation errors and review compiler warnings, which indicate further changes may be needed.
- Start the application and check the console output for startup exceptions or runtime errors.
- Verify the Commerce admin interface loads correctly.
- Test the full order flow: add to cart, apply promotions, checkout, payment processing, and order confirmation.
- Verify catalog management: create, edit, and publish catalog entries and categories.
- Test inventory operations, pricing, and shipping calculations.
- Verify any custom payment provider integrations.
- If using Optimizely Graph Commerce, verify catalog content indexing and search.
- Check for
[Obsolete]deprecation warnings in the build output. These are non-blocking but should be tracked for future cleanup.
ImportantPay special attention to order processing flows that previously used the workflow engine. These are the most likely areas to have runtime issues even after compilation succeeds, because the processing pipeline has fundamentally changed from workflow activities to processor-based APIs.
Updated 12 days ago
