Repository navigation
Releases: Matheis1992/RazorEngine
Release list
RazorEngine.NetFramework 5.0.1
- (FIX) A template is compiled only once when several threads miss the cache for it at the same time (
RunCompile, and layouts and@Includewhile a template runs). Before, every thread compiled it: in a test, 8 threads starting together compiled the same template 8 times. Each of these compiles cost the full compile time and loaded another assembly that stays in memory until itsAppDomainis unloaded, typically when a web application starts and many requests need the same templates. The other threads now wait for the first compile and use its result, or get its exception if it fails (the next call then compiles again); different templates and different model types still compile in parallel. See Caching. - (FIX)
new DefaultCachingProvider(), the caching provider of every newTemplateServiceConfiguration, created a second internal cache that was never disposed. ItsAppDomain.AssemblyResolvehandler stayed registered and kept its objects alive for the life of the process, one per configuration, also after disposing the service. - (PERFORMANCE) The default reference resolver (
UseCurrentAssembliesReferenceResolver) checks each loaded assembly once instead of on every compile. Checking whether an assembly's file exists took about 60 µs per assembly; with 223 loaded assemblies that was about 16 ms per compile and is now below 0.1 ms after the first compile. The references passed to the compiler are the same. - (PERFORMANCE) Anonymous models with lists of anonymous objects (for example
new { Items = list.Select(x => new { x.Name, x.Price }) }) render about 4 times faster. For each list item, the dynamic wrapper of such models first tried the DLR, which cannot bind the enumerator of a list of anonymous types, and only then fell back to reflection: three caught exceptions per item. It now remembers, per type, which members without arguments only work with reflection and calls them directly. In a benchmark with 1000 rows, a run took about 4.5 ms instead of 22 ms, with no exceptions instead of about 3000. The results are the same; missing members still fail as before, and members of dynamic objects such asExpandoObject(which depend on the instance) are resolved as before. - (FIX) A null argument in a call on an anonymous model (for example
@Model.Formatter.Describe(null)) is passed on. Before, the dynamic wrapper failed with aNullReferenceExceptionbefore it bound the call. - (BUILD) Package validation compares both packages with 5.0.0 (also the Roslyn package now), so the 5.0.x releases are checked to be compatible with 5.0.0. The 5.0.0 entries in
CompatibilitySuppressions.xmlare removed with it.
NuGet: https://www.nuget.org/packages/RazorEngine.NetFramework/5.0.1
NuGet (Roslyn): https://www.nuget.org/packages/RazorEngine.NetFramework.Roslyn/5.0.1
RazorEngine.NetFramework 5.0.0
5.0.0 splits RazorEngine into two packages (#22): the core package no longer depends on Roslyn, and Roslyn becomes opt-in. Read Upgrading to 5.0 before updating.
| Package | Contents | Dependencies |
|---|---|---|
RazorEngine.NetFramework |
Razor integration, templating, caching, CodeDom compiler service | Microsoft.AspNet.Razor 3.3.0 |
RazorEngine.NetFramework.Roslyn (new) |
RoslynCompilerServiceFactory, CSharpRoslynCompilerService, RoslynCompilerServiceBase, the metadata reference cache, LanguageVersion |
RazorEngine.NetFramework, Microsoft.CodeAnalysis.CSharp 5.6.0 |
Breaking changes
- (BREAKING) CodeDom is the default compiler again.
DefaultCompilerServiceFactory(the defaultCompilerServiceFactory) compiles templates with CodeDom (thecsc.exeof .NET Framework, C# 5), as before 4.1. Templates that use C# 6 or newer syntax fail to compile unless you install the Roslyn package and setRoslynCompilerServiceFactory. Installing the Roslyn package alone does not change the compiler; it is an explicit opt-in. - (BREAKING) Roslyn moved to
RazorEngine.NetFramework.Roslyn(assemblyRazorEngine.NetFramework.Roslyn.dll, same signing key). The namespaces stay (RazorEngine.Roslyn,RazorEngine.Roslyn.CSharp); only the assembly part of assembly-qualified names changes, for examplecompilerServiceFactoryType="RazorEngine.Roslyn.RoslynCompilerServiceFactory, RazorEngine.NetFramework.Roslyn". - (BREAKING)
DefaultCompilerServiceFactory.LanguageVersionremoved. UseRoslynCompilerServiceFactory.LanguageVersion.RoslynCompilerServiceFactoryno longer derives fromDefaultCompilerServiceFactory; it implementsICompilerServiceFactorydirectly. - (BREAKING) Templates compiled with CodeDom are C# 5 again: code that relied on
fieldas the C# 14 backing field changes meaning back (see the 4.1.0 notes). - (BREAKING) Removed the types that are obsolete since 4.3.0:
CompilerServiceBuilder(RazorEngine never used it; setCompilerServiceFactoryon theTemplateServiceConfiguration) andHtmlTemplateBase<T>(useTemplateBase<T>). - (BREAKING) Removed the members that are obsolete since 3.x:
TemplateBase.RazorEngineandITemplate.RazorEngine: useRazor. Templates can now use theRazorEnginenamespace without it being hidden by this property.DynamicViewBag.AddDictionaryValues,AddDictionaryValuesExandAddListValues: useAddDictionaryorAddValue.
- (BREAKING) As announced in 4.3.0, the implementation details
IsolatedRazorEngineService.SanboxHelper,CrossAppDomainCleanUp.CleanupHelperandCleanupHelper.SubscribeHelperare internal. They were hidden from IntelliSense since 4.3.0 and only meant for RazorEngine's own AppDomain communication.
New
- (NEW) The Roslyn package depends on exactly the same version of the core package (
[5.0.0]), because both are released together and the Roslyn compiler service builds on the core's compiler base classes. - (NEW) Modern C# with CodeDom, without Roslyn in your process.
CodeDomCompilerServiceFactory(andDefaultCompilerServiceFactory, which now derives from it) hasCodeDomProviderFactoryto compile with anotherCodeDomProvider, for example Microsoft.CodeDom.Providers.DotNetCompilerPlatform, andCompilerOptionsfor additional compiler switches such as/langversion:7.3(with a provider that supports it).CSharpDirectCompilerServicehas a constructor that takes theCodeDomProvider; the compiler service disposes it.DirectCompilerServiceBasehasCompilerOptionsand aConfigureCompilerParametershook, and a factory derived fromCodeDomCompilerServiceFactorycan create its own service by overridingCreateCSharpCompilerService. See Roslyn. - (PACKAGING) The core package depends only on Microsoft.AspNet.Razor 3.3.0, so applications without the Roslyn package need no binding redirects for Roslyn's System.* dependencies, and ASP.NET no longer loads Roslyn from
binat startup. - (BUILD) Both packages are built, tested and released together with the same version. Package validation of the core package against 4.3.0 lists the intended breaking changes in
CompatibilitySuppressions.xml. - (BUILD) The core tests no longer use Roslyn, which also shows that the core works without it. The tests that compare CodeDom and Roslyn moved to the Roslyn tests.
- (FIX) Null arguments are rejected right away with an
ArgumentNullException, for example inFluentTemplateServiceConfiguration,ActivateUsingandTypeLoader. The checks were Code Contracts calls (Contract.Requires), which the compiler removes unlessCONTRACTS_FULLis defined, so they never ran and anullfailed later with a less clear error. - (BUILD) Removed leftovers of tools the build does not use: the FxCop suppressions (
SuppressMessage, includingGlobalSuppressions.cs) and the Code Contracts[Pure]attributes. They had no effect.
NuGet: https://www.nuget.org/packages/RazorEngine.NetFramework/5.0.0
NuGet (Roslyn): https://www.nuget.org/packages/RazorEngine.NetFramework.Roslyn/5.0.0
RazorEngine.NetFramework 5.0.0-rc.1
Release candidate of 5.0.0: install it with prereleases enabled (Install-Package RazorEngine.NetFramework -Prerelease) and report problems in the issues before the final 5.0.0.
5.0.0 splits RazorEngine into two packages (#22): the core package no longer depends on Roslyn, and Roslyn becomes opt-in. Read Upgrading to 5.0 before updating.
| Package | Contents | Dependencies |
|---|---|---|
RazorEngine.NetFramework |
Razor integration, templating, caching, CodeDom compiler service | Microsoft.AspNet.Razor 3.3.0 |
RazorEngine.NetFramework.Roslyn (new) |
RoslynCompilerServiceFactory, CSharpRoslynCompilerService, RoslynCompilerServiceBase, the metadata reference cache, LanguageVersion |
RazorEngine.NetFramework, Microsoft.CodeAnalysis.CSharp 5.6.0 |
Breaking changes
- (BREAKING) CodeDom is the default compiler again.
DefaultCompilerServiceFactory(the defaultCompilerServiceFactory) compiles templates with CodeDom (thecsc.exeof .NET Framework, C# 5), as before 4.1. Templates that use C# 6 or newer syntax fail to compile unless you install the Roslyn package and setRoslynCompilerServiceFactory. Installing the Roslyn package alone does not change the compiler; it is an explicit opt-in. - (BREAKING) Roslyn moved to
RazorEngine.NetFramework.Roslyn(assemblyRazorEngine.NetFramework.Roslyn.dll, same signing key). The namespaces stay (RazorEngine.Roslyn,RazorEngine.Roslyn.CSharp); only the assembly part of assembly-qualified names changes, for examplecompilerServiceFactoryType="RazorEngine.Roslyn.RoslynCompilerServiceFactory, RazorEngine.NetFramework.Roslyn". - (BREAKING)
DefaultCompilerServiceFactory.LanguageVersionremoved. UseRoslynCompilerServiceFactory.LanguageVersion.RoslynCompilerServiceFactoryno longer derives fromDefaultCompilerServiceFactory; it implementsICompilerServiceFactorydirectly. - (BREAKING) Templates compiled with CodeDom are C# 5 again: code that relied on
fieldas the C# 14 backing field changes meaning back (see the 4.1.0 notes). - (BREAKING) Removed the types that are obsolete since 4.3.0:
CompilerServiceBuilder(RazorEngine never used it; setCompilerServiceFactoryon theTemplateServiceConfiguration) andHtmlTemplateBase<T>(useTemplateBase<T>). - (BREAKING) Removed the members that are obsolete since 3.x:
TemplateBase.RazorEngineandITemplate.RazorEngine: useRazor. Templates can now use theRazorEnginenamespace without it being hidden by this property.DynamicViewBag.AddDictionaryValues,AddDictionaryValuesExandAddListValues: useAddDictionaryorAddValue.
- (BREAKING) As announced in 4.3.0, the implementation details
IsolatedRazorEngineService.SanboxHelper,CrossAppDomainCleanUp.CleanupHelperandCleanupHelper.SubscribeHelperare internal. They were hidden from IntelliSense since 4.3.0 and only meant for RazorEngine's own AppDomain communication.
New
- (NEW) The Roslyn package depends on exactly the same version of the core package (
[5.0.0]), because both are released together and the Roslyn compiler service builds on the core's compiler base classes. - (NEW) Modern C# with CodeDom, without Roslyn in your process.
CodeDomCompilerServiceFactory(andDefaultCompilerServiceFactory, which now derives from it) hasCodeDomProviderFactoryto compile with anotherCodeDomProvider, for example Microsoft.CodeDom.Providers.DotNetCompilerPlatform, andCompilerOptionsfor additional compiler switches such as/langversion:7.3(with a provider that supports it).CSharpDirectCompilerServicehas a constructor that takes theCodeDomProvider; the compiler service disposes it.DirectCompilerServiceBasehasCompilerOptionsand aConfigureCompilerParametershook, and a factory derived fromCodeDomCompilerServiceFactorycan create its own service by overridingCreateCSharpCompilerService. See Roslyn. - (PACKAGING) The core package depends only on Microsoft.AspNet.Razor 3.3.0, so applications without the Roslyn package need no binding redirects for Roslyn's System.* dependencies, and ASP.NET no longer loads Roslyn from
binat startup. - (BUILD) Both packages are built, tested and released together with the same version. Package validation of the core package against 4.3.0 lists the intended breaking changes in
CompatibilitySuppressions.xml. - (BUILD) The core tests no longer use Roslyn, which also shows that the core works without it. The tests that compare CodeDom and Roslyn moved to the Roslyn tests.
- (FIX) Null arguments are rejected right away with an
ArgumentNullException, for example inFluentTemplateServiceConfiguration,ActivateUsingandTypeLoader. The checks were Code Contracts calls (Contract.Requires), which the compiler removes unlessCONTRACTS_FULLis defined, so they never ran and anullfailed later with a less clear error. - (BUILD) Removed leftovers of tools the build does not use: the FxCop suppressions (
SuppressMessage, includingGlobalSuppressions.cs) and the Code Contracts[Pure]attributes. They had no effect.
NuGet: https://www.nuget.org/packages/RazorEngine.NetFramework/5.0.0-rc.1
NuGet (Roslyn): https://www.nuget.org/packages/RazorEngine.NetFramework.Roslyn/5.0.0-rc.1
RazorEngine.NetFramework 4.3.0
No breaking changes; package validation against 4.2.0 checks that in CI. Code that uses one of the newly obsolete types gets a compiler warning (CS0618), which fails the build if warnings are treated as errors.
- (OBSOLETE) Public types without a real use are marked
[Obsolete]and will be removed in 5.0:CompilerServiceBuilder: RazorEngine never used it, so setting its factory had no effect. SetCompilerServiceFactoryon theTemplateServiceConfiguration.HtmlTemplateBase<T>: adds nothing toTemplateBase<T>; useTemplateBase<T>.
- (DOCS) Use
RoslynCompilerServiceFactoryif your templates rely on Roslyn (modern C#, a pinnedLanguageVersion). It does the same asDefaultCompilerServiceFactorytoday, but 5.0 is planned to compile with CodeDom by default again and move Roslyn into a separate package (#22);RoslynCompilerServiceFactorywill keep selecting Roslyn. The examples in Roslyn use it. - Implementation details that are public by accident are hidden from IntelliSense (
[EditorBrowsable(Never)]):IsolatedRazorEngineService.SanboxHelper(despite its name no sandbox),CrossAppDomainCleanUp.CleanupHelperandCleanupHelper.SubscribeHelper. They become internal in 5.0. - (BUILD) Removed dead code that was never compiled or never ran: code disabled with
#if DISABLED(about 400 lines of the embedded Impromptu code, and the unusedIRazorEngineCoreinterface), a regular expression in the Impromptu code that only that code used, the never-compiled Silverlight variants (#if SILVERLIGHT5), a commented-out method, and the Mono code paths in RazorEngine's own code (the fork targets .NET Framework 4.8 on Windows; the Mono checks inside the embedded Impromptu code stay as third-party code). - (BUILD) Removed the remaining unnecessary
usingdirectives (145). - (BUILD) Package validation baseline moved to 4.2.0.
NuGet: https://www.nuget.org/packages/RazorEngine.NetFramework/4.3.0
RazorEngine.NetFramework 4.2.0
-
(NEW) The C# language version of templates can be pinned with
DefaultCompilerServiceFactory.LanguageVersion(also onRoslynCompilerServiceFactory, andCSharpRoslynCompilerService.LanguageVersion). The default stays the newest version the bundled Roslyn supports (C# 14). Pin an older version when a newer C# version changes the meaning of existing templates, see thefieldentry under 4.1.0:config.CompilerServiceFactory = new DefaultCompilerServiceFactory { LanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp13 };
-
(PERFORMANCE) The Roslyn compiler service caches the metadata references of the loaded assemblies templates are compiled against, per
AppDomain, so Roslyn reuses what it read from them instead of reading and analyzing every referenced assembly on each compile. Each compile after the first is about 35 to 50% faster: in a benchmark, about 25 ms instead of 40 ms with 64 loaded assemblies, and about 48 ms instead of 95 ms with 255. The first compile in a process is unchanged (about 2 s for loading Roslyn). A loaded assembly cannot change, so the cache never goes stale; references given as a file path, stream or byte array (by a customIReferenceResolver) are read on every compile. Templates themselves are not cached by this; changed templates are recompiled as before. -
(BUILD)
dotnet packvalidates the package against the last published version (package validation, baseline 4.1.0) and fails on breaking changes of the public API. -
(DOCS) The README links the documentation pages in
doc(with absolute links, so they also work on nuget.org) instead of the original project's website, and its AppDomain example for cleaning up temporary files uses a fully trusted AppDomain instead of suggesting a partially trusted one. -
(DOCS) New page Caching: how compiled templates are cached (template key and model type), what
RunCompile,Compile,RunandIsTemplateCacheddo, the three caching providers with examples for invalidating, why invalidating does not free memory (each recompile loads a new assembly that stays until itsAppDomainis unloaded) and when temporary files are deleted. -
(DOCS) Roslyn shows how to pin
LanguageVersionwhen RazorEngine is configured inapp.config/web.config: derive a factory that sets it in its constructor and name that type incompilerServiceFactoryType. -
(DOCS) Outdated passages removed from the documentation: links to the original project's website, notes about Mono (the fork targets .NET Framework 4.8 on Windows) and an old Travis CI link.
ReferenceResolver.mdexplains which compiler needs which references. -
(BUILD) Removed files and projects that nothing used or shipped:
RazorEngine.Mvc,RazorEngine.Hosts.Console, the old FSharp.Formatting doc site, the class diagram and an unused ruleset. The tests buildTestHelper.dllinstead of using a checked-in binary.
NuGet: https://www.nuget.org/packages/RazorEngine.NetFramework/4.2.0
RazorEngine.NetFramework 4.1.0
4.1.0 switches templates to a modern C# compiler and removes the APIs that were obsolete since 3.5, as well as VB.NET templates.
Unchanged: the template syntax (Razor 3, Microsoft.AspNet.Razor 3.3.0), the namespaces, the assembly name RazorEngine.NetFramework.dll and its signing key, and .NET Framework 4.8.
Read the breaking changes below before updating; doc/Upgrading.md has the migration steps.
Highlights
-
(NEW) Modern C# in templates. Roslyn (Microsoft.CodeAnalysis.CSharp) is updated from 1.3.2 to 5.6.0 and is now the default compiler. Templates can use C# up to C# 14 instead of C# 5: string interpolation,
?.,nameof, tuples and deconstruction, pattern matching, switch expressions and more. For example:<p>@($"Hello {Model.Name}!")</p> <p>@(Model.Nickname?.ToUpper() ?? "no nickname")</p> @{ var text = Model.Age switch { >= 18 => "adult", _ => "child" }; } <p>@text</p>
-
(NEW) Fewer dependencies. The package now only depends on Microsoft.AspNet.Razor 3.3.0 and Microsoft.CodeAnalysis.CSharp 5.6.0. The pins of System.Collections.Immutable 1.3.1, System.Reflection.Metadata 1.4.2 and System.Security.Cryptography.X509Certificates 4.3.2, which only existed for the old Roslyn, are gone.
Breaking changes
-
(BREAKING) Roslyn is the default compiler.
DefaultCompilerServiceFactorynow compiles templates in-process with Roslyn instead of startingcsc.exethrough CodeDom.-
Templates are still compiled optimized and with the
RAZORENGINEpreprocessor symbol, as with CodeDom, so#if RAZORENGINEkeeps working. -
The first compile in a process (or
AppDomain) takes longer, because Roslyn is loaded and JIT-compiled there once: about 2 s instead of about 0.2 s with CodeDom. Later compiles do not start a separatecsc.exeprocess and are faster (in a benchmark about 40 ms instead of about 85 ms; 4.2.0 brings this down to about 26 ms). From about 30 templates per process on, Roslyn is faster overall. -
Roslyn runs inside the process: it needs about 55 MB more memory per process, and per
AppDomainofIsolatedRazorEngineService. -
Debugging: with Roslyn,
Debug = truedoes not let you step into templates with the debugger. -
To keep the old compiler (C# 5,
csc.exe), for example for debugging, use the newCodeDomCompilerServiceFactory:config.CompilerServiceFactory = new RazorEngine.Compilation.CodeDomCompilerServiceFactory();
or in the configuration file:
<razorEngine compilerServiceFactoryType="RazorEngine.Compilation.CodeDomCompilerServiceFactory, RazorEngine.NetFramework">. -
RoslynCompilerServiceFactorystill exists and now does the same asDefaultCompilerServiceFactory.
-
-
(BREAKING) C# 14 can change the meaning of existing template code. Templates were compiled as C# 5 before and are compiled with the newest C# version now. Code that compiles with both usually behaves the same, with one known exception that does not cause a compile error:
- Since C# 14,
fieldinside a property accessor is the property's backing field. A template that declares its own member namedfield(for example in@functions) and returns it from a property accessor now gets the backing field instead (for examplenull). - Rename the member, or, from 4.2.0 on, pin
LanguageVersion.CSharp13(see 4.2.0), or keep the CodeDom compiler. - Roslyn lists all C# breaking changes in https://github.com/dotnet/roslyn/tree/main/docs/compilers/CSharp.
- Since C# 14,
-
(BREAKING) Binding redirects for Roslyn's dependencies. Roslyn 5.6.0 brings newer System.* assemblies (System.Collections.Immutable 10, System.Reflection.Metadata 10, System.Memory and others). .NET Framework applications need binding redirects for them:
-
SDK-style projects generate them automatically (
AutoGenerateBindingRedirects). -
For packages.config projects, NuGet adds them to
app.config/web.configon install. Check that existing, hand-written redirects for these assemblies point to the new versions. -
A
FileLoadExceptionfor one of these assemblies at the first template compile means a binding redirect is missing. -
Custom
AppDomains forIsolatedRazorEngineServiceneed the application's configuration file, otherwise the redirects do not apply there.IsolatedRazorEngineService.Create()already does this; for your own domains set it yourself:var setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase, ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile }; var service = IsolatedRazorEngineService.Create(() => AppDomain.CreateDomain("Templates", null, setup));
-
-
(BREAKING) Legacy API removed (obsolete since 3.5). Replacements:
Removed Use instead Razor.Parse(template, model, name)Engine.Razor.RunCompile(template, name, null, model)Razor.Compile(template, modelType, name)Engine.Razor.Compile(template, name, modelType)Razor.Run(name, model)Engine.Razor.Run(name, null, model)TemplateService,ITemplateServiceRazorEngineService.Create(config),IRazorEngineServiceIsolatedTemplateServiceIsolatedRazorEngineService.Create(...)ITemplate.TemplateService,TemplateBase.TemplateServiceTemplateBase.RazorParallel query plans ( IParallelQueryPlan, ...)your own Parallel.ForEach/PLINQ aroundRunThe
RunCompile/Compile/Runoverloads with a template string are extension methods inRazorEngine.Templating. -
(BREAKING) Template resolvers removed (obsolete since 3.5). Template managers replace them:
Removed Use instead ITemplateResolver,DelegateTemplateResolverITemplateManager, e.g.DelegateTemplateManager,ResolvePathTemplateManager,EmbeddedResourceTemplateManagerconfig.Resolverconfig.TemplateManagerResolveUsing(ITemplateResolver),ResolveUsing<TResolver>()ManageUsing(...),ManageUsing<TManager>()(ResolveUsing(Func<string, string>)stays)templateResolverType="..."in the configuration filetemplateManagerType="..."WrapperTemplateManageran ITemplateManagerimplementationA configuration file that still sets
templateResolverTypenow fails to load with aConfigurationErrorsExceptioninstead of being ignored. -
(BREAKING) Code inspectors removed (obsolete since 3.5):
ICodeInspector, theCodeInspectorsproperties of the compiler service and the configurations,AddInspectorandInspect(). There is no replacement. They were no security boundary either: templates must come from trusted sources. -
(BREAKING) APIs announced for removal in 4.0 removed:
TemplateCompilationException.Errors: useCompilerErrors.ICompilerService.IncludeAssemblies()andCompilerServiceBase.IncludeAssemblies(): useIncludeReferences().- The
ExecuteContext(DynamicViewBag)constructor: it always threw; pass the view bag toRun/RunCompileinstead. - The public
TypeHashconstructors of the embedded Impromptu code: useTypeHash.Create.
-
(BREAKING) VB.NET templates removed. Removed are
Language.VisualBasic, theRazorEngine.Compilation.VisualBasiccompiler services,CompilerServicesUtility.ResolveVBTypeName/VBGetRawTypeName/VBCreateGenericType, the VB parser inRazorEngineHostand the.vbhtmllookup ofResolvePathTemplateManager.- Templates are always C#. Convert
.vbhtmltemplates to.cshtml. - A configuration file with
language="VisualBasic"ordefaultLanguage="VisualBasic"fails to load. - VB.NET applications can still use RazorEngine with C# templates and pass their own (also anonymous) objects as models.
- Templates are always C#. Convert
Fixes
- (BUGFIX) The Roslyn compiler service now prepares the generated code like the CodeDom one. Before, with Roslyn, base template types with constructor parameters failed to compile, dynamic models were not marked, and
#line hiddenwas not removed for debugging. - (BUGFIX) The Roslyn compiler service now compiles optimized and defines
RAZORENGINE, like CodeDom always did.
Build and tests
- (BUILD) New tests check that both compilers optimize and define
RAZORENGINE, compile modern C# (C# 6 to 8 samples) with Roslyn, and keep the CodeDom fallback tested. - (BUILD) The release workflow publishes tagged versions to nuget.org with trusted publishing (introduced for 4.0.0).
- (PACKAGING) The copyright notice of the package and the assembly keeps the original project's notice and adds the fork's:
Copyright © 2011-2017 RazorEngine Project, © 2026 RazorEngine.NetFramework contributors.
NuGet: https://www.nuget.org/packages/RazorEngine.NetFramework/4.1.0
RazorEngine.NetFramework 4.0.0
- (BREAKING) First release of the fork, published as the new package
RazorEngine.NetFramework. - (SECURITY, BREAKING) Fix CVE-2021-46703 (sandbox escape in
IsolatedRazorEngineService):IsolatedRazorEngineServiceandIsolatedTemplateServicenow refuse partially trusted (sandboxed)AppDomains with aNotSupportedException, because Code Access Security is no security boundary. Isolation with fully trustedAppDomains (to unload templates) works as before. Templates must come from trusted sources; see doc/Isolation.md. - (BREAKING) The assembly is now
RazorEngine.NetFramework.dll, signed with a new key (public key token58ad996d4f48e61f), so it no longer collides with the originalRazorEngine.dll. Namespaces stayRazorEngine.*. When migrating, updateapp.config/web.config:- Change the assembly name of the section registration, e.g.
type="RazorEngine.Configuration.RazorEngineConfigurationSection, RazorEngine.NetFramework". - Change every assembly-qualified type name inside
<razorEngine>that names, RazorEngine(activatorType,baseTemplateType,cachingProviderType,compilerServiceFactoryType,encodedStringFactoryType,referenceResolverType,templateManagerType,templateResolverType). - Remove
bindingRedirectentries for the oldRazorEngineassembly.
- Change the assembly name of the section registration, e.g.
- (BUGFIX) The default reference resolver no longer passes the original
RazorEngine/RazorEngine.Roslyn3.x assemblies to the template compiler, so templates still compile when the original package is loaded in the same process. - (NEW) Roslyn is part of the package. In the original project it was the separate package
RazorEngine.Roslyn(last 4.1.1-rc1); the fork contains the never-released upstream change from 3.10.1-alpha001 that merged it into the main assembly, soRoslynCompilerServiceFactoryis available without another package. RemoveRazorEngine.Roslynwhen switching. CodeDom (csc.exe, C# 5) stays the default compiler in 4.0.0. - (PACKAGING) Because of that, the package now depends on Microsoft.CodeAnalysis.CSharp 1.3.2, System.Collections.Immutable 1.3.1 and System.Reflection.Metadata 1.4.2 in addition to Microsoft.AspNet.Razor (the original 3.10.0 only depended on Razor).
- (NEW) Values in a
DynamicViewBagare exchanged acrossAppDomains, so a view bag works withIsolatedRazorEngineService(never-released upstream change, thanks campersau, Antaris#504). - (BREAKING) Target .NET Framework 4.8 only. The net40 (Razor 2) and Razor4 (Microsoft.AspNetCore.Razor) builds are dropped.
- (BUILD) SDK-style projects with NuGet PackageReference replace Paket and FAKE. Build with
dotnet build, test withdotnet test, pack withdotnet pack. - (BUILD) GitHub Actions replace Travis CI and AppVeyor.
- (PACKAGING) The package has the
Apache-2.0license expression, contains README and LICENSE, comes with a symbol package (.snupkg) on nuget.org and is built deterministically on GitHub Actions. - (BUILD) Releases are published from GitHub Actions: pushing a version tag builds, tests and packs that commit, pushes the package to nuget.org with trusted publishing and creates the GitHub release.
- (BREAKING) Requires Microsoft.AspNet.Razor 3.3.0 (3.x maintenance release, the parser is unchanged since 3.2.3, so template syntax is unchanged from the 3.x net45 build). ASP.NET MVC 5.2.x only allows Razor below 3.3.0: apps using MVC have to update to Microsoft.AspNet.Mvc 5.3.0 (and Microsoft.AspNet.WebPages 3.3.0) to install this package, otherwise NuGet reports a version conflict (NU1107).
- (PACKAGING) Depend on System.Security.Cryptography.X509Certificates 4.3.2 instead of the 4.1.0 pulled in by Roslyn. NuGet audit flags 4.1.0 for CVE-2017-11770, which only affects .NET Core, not .NET Framework; the pin keeps the audit warning away from consumers.
- (BUILD) Tests use NUnit 5 (constraint model asserts), Moq 4.21 and Autofac 9; RazorEngine.Mvc uses Microsoft.AspNet.Mvc 5.3.0. Package versions are managed centrally in
src/Directory.Packages.props.
NuGet: https://www.nuget.org/packages/RazorEngine.NetFramework/4.0.0