Area: Optimizely CMS
Applies to versions: 12 and higher

Migrating add-ons from .NET Framework to .NET 5

Recommended reading 
Note: This documentation is for the preview version of the upcoming release of CMS 12/Commerce 14/Search & Navigation 14. Features included here might not be complete, and might be changed before becoming available in the public release. This documentation is provided for evaluation purposes only.

Microsoft has the following guidelines for migrating to .NET 5: Overview of porting from .NET Framework to .NET 5.

If your add-on contains views, configure the the assembly for precompiled views by changing the SDK type for the project to Razor as:

<Project Sdk="Microsoft.NET.Sdk.Razor">

You should also add the following property to the .csproj file:


Views locations

To avoid collisions in view locations with the partner website, you should store the views for the add-on under a custom folder in the project. If not specified, the default convention is that views are stored under a top folder <AddonName>.Views, like this:

You also can specify viewFolder in module.config, like this:

<module viewFolder="CmsUIViews" ...

In that case, the views in the project should look like this:

Precompiled views

A shell module or add-on can have views that are distributed as content together with the module/add-on and then at runtime the views are located through an IFileProvider (previously VirtualPathProvider). You can still have views located and compiled at runtime but that requires that the application enables the runtime compilation. The modules/add-on should precompile the views and distribute them in an assembly (typically named <addon>.Views.dll) instead.

To avoid risk for view conflicts with application/other add-ons, CMS adds, by default, a view location expander that searches for views in location <moduleName>.Views/Views. You can also use the viewFolder attribute in module.config.

Access rights

Previously, shell modules were protected by a configuration for the shell location in web.config (typically path /EPiServer). Instead, each endpoint that is registered for a shell module is associated with a policy.

You can specify the policy to use for the module through the authorizationPolicy attribute in module.config. If you do not specify a value for authorizationPolicy, a module's endpoints are registered with ShellModule.DefaultShellModulePolicy, which requires that user is part of any of the following roles: WebEditors, WebAdmins, CmsAdmins, or Administrators.

Json Serialization

In an ASP.NET Core application, a “global” serializer is registered (by default from System.Text.Json but you can configure it as NewtonSoft). Use the global serializer for model binding of posted data when you use the [FromBody] attribute and when data is returned using OK result, or automatic IActionResult conversion.

You should not rely on the global serializer for add-ons or modules because the end application can configure it in different ways (such as pascal or camel-casing). You should let each module register its own preferred serializer.

If no specific configuration is needed, then it can be specified in module.config using the moduleJsonSerializerType attribute.

  • Enter the Net value to specify the built-in serializer in net core.
  • Enter Newtonsoft to use Newtonsoft.Json.
  • If the module or add-on requires a custom configuration then it can set a None value and instead call either extension method (to IServiceCollection), UseSystemTextJsonSerialization, or UseNewtonsoftSerialization.

The extension methods let the serializer have a custom configuration. You can register a serializer per assembly but also override per type.

Do you find this information helpful? Please log in to provide feedback.

Last updated: Jul 02, 2021

Recommended reading