Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Razor fails to delete dynamic template dll files and trashes filesystem

Tags:

c#

razorengine

After upgrading from Razor templating engine 3.3.0 to 3.6.1 I've run into issues with precompiled templates - what happens is that even the trivial sample given on their page:

using System;
using RazorEngine;
using RazorEngine.Templating;
using System.Diagnostics;

namespace RazorTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string template = "Hello @Model.Name, welcome to RazorEngine!";
            Debug.WriteLine("Before Compile()");
            var result = Engine.Razor.RunCompile(template, "templateKey", null, new { Name = "World" });
            Debug.WriteLine("After Compile()");
         }
    }
}

Throws System.UnauthorizedAccessException on exit when trying to delete the generated dll files. The debug output shows everything quite nicely:

Before Compile()
'RazorTest.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Users\user\Documents\Visual Studio 2010\Projects\RazorTest\RazorTest\bin\Debug\System.Web.Razor.dll'
'RazorTest.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Users\user\AppData\Local\Temp\RazorEngine_zzxr14ak.ysb\CompiledRazorTemplates.Dynamic.RazorEngine_dc2066212315402592a6d2d155476c19.dll'
'RazorTest.vshost.exe' (Managed (v4.0.30319)): Loaded 'Anonymously Hosted DynamicMethods Assembly'
'RazorTest.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Dynamic\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Dynamic.dll'
A first chance exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Microsoft.CSharp.dll
A first chance exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Microsoft.CSharp.dll
After Compile()
The thread 'vshost.RunParkingWindow' (0x3064) has exited with code 0 (0x0).
The thread '<No Name>' (0x2df0) has exited with code 0 (0x0).
A first chance exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll
A first chance exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll
A first chance exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll
The program '[26908] RazorTest.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).

The dll file is loaded by the application during compilation so it makes sense that if some kind of unloading is not done Razor will not be able to delete it, and the files are left on the disk.

What else seems weird that even though the type of the model is given Razor considers the template to be dynamic (at least judging from the dll name).

Has anyone more experienced with Razor encountered this or can provide some hints on how to overcome this issue?

like image 355
Rudolfs Bundulis Avatar asked Mar 05 '15 13:03

Rudolfs Bundulis


1 Answers

There was a problem with temporary files, which has been fixed in 3.6.4 (for the most part). If you want details please read https://github.com/Antaris/RazorEngine/issues/244. There are still first chance exceptions of type 'System.UnauthorizedAccessException', but they handled internally by RazorEngine.

Your template is in fact compiled with dyanmic as model-type because you have given null = dynamic as the modeltype parameter.

If you want to compile your template with a static type use

Engine.Razor.RunCompile(template, "templateKey", typeof(MyModel), new MyModel());

The reason we made the type explicit is because you can now re-use the same template for multiple types by either specifying a common base type or by explicitly using null = dynamic:

// Will compile only once
Engine.Razor.RunCompile(template, "templateKey", typeof(MyBaseModel), new MyModel1());
Engine.Razor.RunCompile(template, "templateKey", typeof(MyBaseModel), new MyModel2());
// Will start a new compilation, and load another assembly
Engine.Razor.RunCompile(template, "templateKey", typeof(MyModel3), new MyModel3());

this works as long as MyModel1 and MyMode2 inherit from MyBaseModel. Or you can use dynamic:

// Will compile only once
Engine.Razor.RunCompile(template, "templateKey", null, new FirstModel());
Engine.Razor.RunCompile(template, "templateKey", null, new SecondModel());

Note that with dynamic your models don't even need to inherit from the same base type. As long as FirstModel and SecondModel have all properties, which are required by the template, it will work (but it will fail not at template-compilation but at template-runtime).

This is especially useful for included and layout templates (which is a lot more customizable now).

Hope this helps. matthid, a RazorEngine contributor.

like image 128
matthid Avatar answered Oct 02 '22 09:10

matthid