RazorEngine icon indicating copy to clipboard operation
RazorEngine copied to clipboard

Introduction of CrossAppDomainCleanUp causing issues with non-serializable objects

Open madelson opened this issue 10 years ago • 6 comments

One of the recent upgrades to RazorEngine has led us to start seeing errors like the following:

Error message: Type '[some type]' in assembly '[some assembly]' is not marked as serializable.
at System.AppDomain.InternalCreateInstanceFromWithNoSecurity(String assemblyName, String typeName)
at RazorEngine.Compilation.CrossAppDomainCleanUp.InitHelper.CreateHelper()
at RazorEngine.Compilation.ExecutionContextLessThread.CallHelperSafeHelper`2.AsAction()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at RazorEngine.Compilation.ExecutionContextLessThread.DefaultCallFunc[O](Func`1 f)
at RazorEngine.Compilation.CrossAppDomainCleanUp..ctor(AppDomain toWatch, IPrinter printer)
at RazorEngine.Compilation.CrossAppDomainCleanUp.CreateInitial()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at RazorEngine.Compilation.CrossAppDomainCleanUp.RegisterCleanup(String item, Boolean throwOnDefault)
at RazorEngine.Templating.InvalidatingCachingProvider.CacheTemplate(ICompiledTemplate template, ITemplateKey templateKey)
at RazorEngine.Templating.RazorEngineService.CompileAndCacheInternal(ITemplateKey key, Type modelType)

In this case "some type" and "some assembly" are a custom identity type we use which is not serializable. While we could try to get the creator of that type to be serializable, I wanted to first understand why this was happening and whether there was anything other than make our code 100% remoting compliant in order to keep upgrading RazorEngine.

EDIT: looking into this more, it seems like it's a resurgence of https://github.com/Antaris/RazorEngine/issues/267, where the ExecutionContextLessThread does not seem to be successfully suppressing the execution context.

madelson avatar Sep 28 '15 15:09 madelson

Yes this is a bug in RazorEngine, thanks for reporting this. This is releated to https://github.com/Antaris/RazorEngine/issues/275 as well. And the workaround is the same:

config.CachingProvider = new DefaultCachingProvider(t => {});
config.DisableTempFileLocking = true;

Can you provide a simplified repro for this (Or at least show me how you implemented your custom identity type)? It is really weird because we try to start a new thread for the sole purpose to get a 'clean' ExecutionContext (so there is nothing to serialize). However, some things seem to slip through. I'm starting to think that this is some WinAPI specific thing, where the context is saved within the (windows-)thread itself and not the '.net' ExecutionContext.

matthid avatar Sep 28 '15 18:09 matthid

I don't have a small repro handy, but here are some details that might be relevant.

  • The identity in question is a POCO that implements the IIdentity interface. We're using it with a GenericPrincipal
  • The error occurs when the code is running as part of a ASP.NET application (we use RazorEngine for SQL query templating in a web app)
  • The identity is set during one of the early ASP.NET request lifecycle events, but the observed error occurs in the normal MVC request-handling thread

madelson avatar Sep 30 '15 01:09 madelson

Had the same bug with a custom implementation of IIdentity

config.CachingProvider = new DefaultCachingProvider(t => {});
config.DisableTempFileLocking = true;

Fixed it. Thanks!

NicoJuicy avatar Nov 12 '15 12:11 NicoJuicy

Any code sample (ideally simplified) reproducing the problem would be appreciated. I already tried fixing that "blindly" but no approach seems to fetch all cases.

matthid avatar Nov 21 '15 09:11 matthid

@matthid This error occurs if I use CallContext.LogicalSetData before method IsolatedRazorEngineService.Create() and set an entity that is not marked [Serializable].

here is a demo to produce this error.

using RazorEngine.Templating;
using System.Runtime.Remoting.Messaging;

namespace WorkerRole
{
    public class User
    {
        public string Name { get; set; }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            var user = new User();
            CallContext.LogicalSetData("123", user);
            using (var service = IsolatedRazorEngineService.Create())
            {
            }
        }
    }
}

error is

System.Runtime.Serialization.SerializationException: 'Type 'WorkerRole.User' in assembly 'WorkerRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.'

cysnet avatar Mar 28 '24 03:03 cysnet

I create a new issue to track this problem.

https://github.com/Antaris/RazorEngine/issues/601

cysnet avatar Mar 28 '24 03:03 cysnet