Repository navigation
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