Antaris / RazorEngine

Open source templating engine based on Microsoft's Razor parsing engine
http://antaris.github.io/RazorEngine
Other
2.14k stars 577 forks source link

Razor Engine throws error on compiling Templates #433

Open ashishjw opened 7 years ago

ashishjw commented 7 years ago

Hi, Razor Engine throws ArgumentOutOfRangeException on RunCompile method, Below is the stack trace for the same. This is one very weird issue i am facing, although it run fine on dev branch , this issue comes on prod, template which we are using is same on dev and prod branches as well as the dll version of Razor Engine.

Exception : System.ArgumentOutOfRangeException: Length cannot be less than zero.
Parameter name: length
   at System.String.Substring(Int32 startIndex, Int32 length)
   at RazorEngine.Compilation.CompilerServicesUtility.CSharpGetRawTypeName(Type type)
   at RazorEngine.Compilation.CompilerServicesUtility.CSharpCreateGenericType(Type templateType, String modelTypeName, Boolean throwWhenNotGeneric)
   at RazorEngine.Compilation.CompilerServiceBase.CreateHost(Type templateType, Type modelType, String className)
   at RazorEngine.Compilation.CompilerServiceBase.GetCodeCompileUnit(TypeContext context)
   at RazorEngine.Compilation.DirectCompilerServiceBase.Compile(TypeContext context)
   at RazorEngine.Compilation.DirectCompilerServiceBase.CompileTypeImpl(TypeContext context)
   at RazorEngine.Compilation.DirectCompilerServiceBase.CompileType_Windows(TypeContext context)
   at RazorEngine.Compilation.DirectCompilerServiceBase.CompileType(TypeContext context)
   at RazorEngine.Templating.RazorEngineCore.CreateTemplateType(ITemplateSource razorTemplate, Type modelType)
   at RazorEngine.Templating.RazorEngineCore.Compile(ITemplateKey key, Type modelType)
   at RazorEngine.Templating.RazorEngineService.CompileAndCacheInternal(ITemplateKey key, Type modelType)
   at RazorEngine.Templating.RazorEngineService.GetCompiledTemplate(ITemplateKey key, Type modelType, Boolean compileOnCacheMiss)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass15_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)

and my template looks like this

@using RazorEngine
@using IntranetDASHBOARD.Core
@using IntranetDASHBOARD.Core.MVC.Models.Emails
@inherits  IntranetDASHBOARD.Core.MVC.TemplateBase<iDNotification>

@DBSystem.ConfigSettings.Get("SYSTEM_NAME") - @Text.LocalizeForHtml("Wiki_Text_AccessRequest_NotificationEmail")

Hello @Model.CurrentUser.FullName
@Text.LocalizeForHtml("Wiki_Notifications_PageChanged")

@foreach (iDNotificationActivity Page in Model.Notifications)
{
    @:@Page.OperationTimeFriendly - @Page.ItemType (@Page.ItemTitle) : @Page.Operation by @Page.FullName

    if (!Page.ItemLineage.StartsWith("|"))
    {
    @:@Text.LocalizeForHtml("phr_ViewThisPage") @DBSystem.Values.HostName@Page.ItemLineage
    }
    else
    {
    @:@Text.LocalizeForHtml("phr_NoLongerViewThisItem")
    }
    @:
}
matthid commented 7 years ago

Seems like your template type is a generic type with an unexpected full name. Can you tell me more about the IntranetDASHBOARD.Core.MVC.TemplateBase<iDNotification> type?

Can you show the typeof(T).FullName string for all relevant types (including the full generic type, the generic type-defs and all parameters)?

matthid commented 7 years ago

The following code is failing for your type.

If you could provide a unit test with a fix as PR that would be awesome!

ashishjw commented 7 years ago

Hey matthid, Thanks for the reply. It turned out to be an obfuscation issue for us which got resolved when we de-obfuscated namespaces for the class where we have used Razor Engine. Its all good now running great.

matthid commented 7 years ago

We problably should still work with the obfuscated code. I'd say it's still a bug but not as urgent as I initially assumed. The requested info would still help...

ashishjw commented 7 years ago

May be but i am not so convinced, the reason for that is the way we have implemented obfuscation through dotfuscator tool internally. The namespaces which are mentioned in the template have been obfuscated and we cannot refer to obfuscated code from say aspx and cshtml page. If we do so then we have to exclude them from obfuscation. The reason for this error i am assuming is after obfuscation template type which is "IntranetDASHBOARD.Core.MVC.Models.Emails.iDNotification" name has been renamed to something else and then this code (type.FullName.IndexOf('`')) inside CSharpGetRawTypeName is causing exception.

Although i can still give you information which you have requested - "iDNotification" is the model inside MVC.Models.Emails namespace(obfuscation of which was causing issue) . It has a property Notifications As List(Of iDNotificationActivity) which contains all the information about Notifications. Template base is Generic class(TemplateBase(Of T)). And typeof(T).Fullname is IntranetDASHBOARD.Core.MVC.Models.Emails.iDNotification

matthid commented 7 years ago

@ashishjw I see what you are saying: Because of the obfuscation the template is invalid and RazorEngine is unable to compile it. But that is only half of the truth, because you can remove the @inherits IntranetDASHBOARD.Core.MVC.TemplateBase<iDNotification> line and set it programmatically (by setting a template-base in the configuration). Now it still wouldn't compile, because all fields are removed/renamed/obfuscated. But in theory a empty template (or a template using only System stuff should work. Even when using a obfuscated template-base.

What I'm saying is that our code is failing too early (which is the bug you found). We would need the "obfuscated" type name to fix it. But the bug is really really minor, because - as you noticed - we still couldn't compile the template in all practical cases later on.

amoraitis commented 4 years ago

Any updates on this one? I am getting the same error in a previously working template.