Skip to content
This repository was archived by the owner on Mar 19, 2024. It is now read-only.
This repository was archived by the owner on Mar 19, 2024. It is now read-only.

Problem (because of clean-up?) when running in IIS #1

@chucker

Description

@chucker

I'm trying to use IsolatedRazor to build HTML e-mails based on Razor templates. This is inside an ASP.NET Web API project; IsolatedRazor lives inside an ApiController and gets called on a schedule using FluentScheduler.

Intermittently, but frequently enough that it's not practical to use right now, I get one of two errors:

  • a FileNotFoundException trying to load ImpromptuInterface or one of its dependencies. Here's an example stacktrace:
2018-05-04 06:00:02.6015|3|ERROR|TAG.Accounts.WebApi.Controllers.Statistics.NightlyUserAccountStatisticsController|System.AggregateException: Mindestens ein Fehler ist aufgetreten. ---> System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> System.IO.FileNotFoundException: Die Datei oder Assembly "ImpromptuInterface, Version=6.2.2.0, Culture=neutral, PublicKeyToken=0b1781c923b2975b" oder eine Abh�ngigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.
   bei IsolatedRazor.DynamicViewBag..ctor(Object parentViewBag)
   bei IsolatedRazor.TemplateBase..ctor()
   bei IsolatedRazor.RazorTemplate.C_GetTemplate_SummaryTableAsync..ctor()
   --- Ende der internen Ausnahmestapel�berwachung ---
   bei System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   bei System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   bei System.Activator.CreateInstance(Type type, Boolean nonPublic)
   bei System.Activator.CreateInstance(Type type)
   bei IsolatedRazor.RazorTemplater.PrepareTemplate(String assemblyPath, String typeName, DynamicViewBag viewBag, TemplateCache templateCache, TemplateEncoding encoding)
   bei IsolatedRazor.RazorTemplater.RenderTemplateInternal[T](String assemblyPath, String typeName, T model, DynamicViewBag viewBag, TemplateCache templateCache, TemplateEncoding encoding)
   bei IsolatedRazor.RazorTemplater.RenderTemplateInternal[T](String assemblyPath, String typeName, T model, DynamicViewBag viewBag, TemplateCache templateCache, TemplateEncoding encoding)
   bei IsolatedRazor.RazorTemplater.<>c__DisplayClass4c`1.<Render>b__4b()
   bei System.Threading.Tasks.Task`1.InnerInvoke()
   bei System.Threading.Tasks.Task.Execute()
  • or an UnauthorizedAccessException trying to delete a generated template DLL:
2018-04-25 23:03:51.5419|2|ERROR|TAG.Accounts.WebApi.WebApiApplication|System.UnauthorizedAccessException: Der Zugriff auf den Pfad "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\15a0a301\13ba4d00\_GetTemplate_SummaryTableAsync.dll" wurde verweigert.
   bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   bei System.IO.File.InternalDelete(String path, Boolean checkHost)
   bei IsolatedRazor.RazorTemplater.Dispose()
   bei IsolatedRazor.RazorTemplater.Finalize() 

This happens regardless of whether I set persistTemplates to true. Other than that, IsolatedRazor gets called like so:

                using (var templateEngine = new IsolatedRazor.RazorTemplater(templateAssemblyPath, renderTimeout: 5000))
                {
[..various calls to merge portions of the templates..]

// …the final piece:

                    return await _GetTemplate_StatisticsAsync(summaryTable, newAccountsTable, unusedAccountsTable, templateEngine);
                }

And on the inside:

        private async Task<string> _GetTemplate_StatisticsAsync(string summaryTable, string newAccountsTable, string unusedAccountsTable, IsolatedRazor.RazorTemplater templateEngine)
        {
            var result = new Models.Statistics
            {
                SummaryTable = summaryTable,
                NewAccountsTable = newAccountsTable,
                UnusedAccountsTable = unusedAccountsTable,
            };

            var template = System.IO.File.ReadAllText(System.Web.Hosting.HostingEnvironment.MapPath("~/Mails/TemplateHTML/NightlyUserAccountStatistics.cshtml"));

            return await _ParseTemplate(templateEngine, template, result);
        }

        private async Task<string> _ParseTemplate<T>(IsolatedRazor.RazorTemplater templateEngine,
                                                     string template,
                                                     T model,
                                                     [System.Runtime.CompilerServices.CallerMemberName] string caller = "")
        {
            var templateName = caller;

            return await templateEngine.ParseAsync(templateName, template, DateTime.Now, model);
        }

I'm guessing the two exceptions are related: when the clean-up fails in IsolatedRazor.RazorTemplater.Dispose(), IsolatedRazor can't subsequently load its references in IsolatedRazor.TemplateBase..ctor(). However, I'm not sure about that.

I also believe I observed that when this does happen, IsolatedRazor no longer tries to run in its own app domain.

This is unfortunately not 100% reproducible (as far as I can see).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions