toddams / RazorLight

Template engine based on Microsoft's Razor parsing engine for .NET Core
Apache License 2.0
1.5k stars 259 forks source link

RazorLight not working in single-file bundle #429

Open afucher opened 3 years ago

afucher commented 3 years ago

Describe the bug I'm trying to use this package but when I publish using -p:PublishSingleFile=true, my application throws an error when the code touch this library.

To Reproduce Steps to reproduce the behavior:

  1. Build a project using RazorLight
  2. Publish the project using the argument -p:PublishSingleFile=true, for example: dotnet publish . -c Release -r win-x64 -p:PublishSingleFile=true
  3. Run the project, and make the application run the specific part that use RazorLight

Expected behavior I expected that my application works.

fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HM6E5ELP1500", Request id "0HM6E5ELP1500:00000002": An unhandled exception was thrown by the application.
      System.NotSupportedException: CodeBase is not supported on assemblies loaded from a single-file bundle.
         at System.Reflection.RuntimeAssembly.get_CodeBase()
         at Microsoft.Extensions.DependencyModel.DependencyContextLoader.GetNormalizedCodeBasePath(Assembly assembly)
         at Microsoft.Extensions.DependencyModel.DependencyContextLoader.GetDepsJsonPath(Assembly assembly)
         at Microsoft.Extensions.DependencyModel.DependencyContextLoader.LoadAssemblyContext(Assembly assembly, IDependencyContextReader reader)
         at Microsoft.Extensions.DependencyModel.DependencyContextLoader.Load(Assembly assembly)
         at Microsoft.Extensions.DependencyModel.DependencyContext.Load(Assembly assembly)
         at RazorLight.Compilation.RoslynCompilationService.GetDependencyContextCompilationOptions()
         at RazorLight.Compilation.RoslynCompilationService.EnsureOptions()
         at RazorLight.Compilation.RoslynCompilationService.get_ParseOptions()
         at RazorLight.Compilation.RoslynCompilationService.CreateSyntaxTree(SourceText sourceText)
         at RazorLight.Compilation.RoslynCompilationService.CreateCompilation(String compilationContent, String assemblyName)
         at RazorLight.Compilation.RoslynCompilationService.CompileAndEmit(IGeneratedRazorTemplate razorTemplate)
         at RazorLight.Compilation.RazorTemplateCompiler.CompileAndEmit(RazorLightProjectItem projectItem)
         at RazorLight.Compilation.RazorTemplateCompiler.OnCacheMissAsync(String templateKey)
      --- End of stack trace from previous location ---
         at RazorLight.EngineHandler.CompileTemplateAsync(String key)
         at RazorLight.EngineHandler.CompileRenderAsync[T](String key, T model, ExpandoObject viewBag)
         at aera_core.Controllers.DownloadController.geraLista(Int32 id)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

Information (please complete the following information):

Additional context

marcosdimitrio commented 3 years ago

I experienced the same problem but with a different error message.

Everything works fine locally, but when I publish it I get:

RazorLight: Can't load metadata reference from the entry assembly. Make sure 
PreserveCompilationContext is set to true in *.csproj file

Stack trace:
at RazorLight.Compilation.DefaultMetadataReferenceManager.Resolve(Assembly assembly, DependencyContext dependencyContext)
at RazorLight.Compilation.DefaultMetadataReferenceManager.Resolve(Assembly assembly)
at RazorLight.Compilation.RoslynCompilationService.EnsureOptions()
at RazorLight.Compilation.RoslynCompilationService.get_ParseOptions()
at RazorLight.Compilation.RoslynCompilationService.CreateSyntaxTree(SourceText sourceText)
at RazorLight.Compilation.RoslynCompilationService.CreateCompilation(String compilationContent, String assemblyName)
at RazorLight.Compilation.RoslynCompilationService.CompileAndEmit(IGeneratedRazorTemplate razorTemplate)
at RazorLight.Compilation.RazorTemplateCompiler.CompileAndEmit(RazorLightProjectItem projectItem)
at RazorLight.Compilation.RazorTemplateCompiler.OnCacheMissAsync(String templateKey)
--- End of stack trace from previous location ---
at RazorLight.EngineHandler.CompileTemplateAsync(String key)
at RazorLight.EngineHandler.CompileRenderAsync[T](String key, T model, ExpandoObject viewBag)
at MyApplication.MyTemplateParser.CompileAsync(TemplateDto templateDto)
...

If I set PublishSingleFile to False in the Publish Profile, then the error disappears:

<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121. 
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    ...
    <PublishSingleFile>False</PublishSingleFile>
    ...
  </PropertyGroup>
</Project>

Additional information

b0wter commented 3 years ago

This also happens to me on linux (Ubuntu 20.04).

b0wter commented 3 years ago

I experienced the same problem but with a different error message.

Everything works fine locally, but when I publish it I get:

RazorLight: Can't load metadata reference from the entry assembly. Make sure 
PreserveCompilationContext is set to true in *.csproj file

Stack trace:
at RazorLight.Compilation.DefaultMetadataReferenceManager.Resolve(Assembly assembly, DependencyContext dependencyContext)
at RazorLight.Compilation.DefaultMetadataReferenceManager.Resolve(Assembly assembly)
at RazorLight.Compilation.RoslynCompilationService.EnsureOptions()
at RazorLight.Compilation.RoslynCompilationService.get_ParseOptions()
at RazorLight.Compilation.RoslynCompilationService.CreateSyntaxTree(SourceText sourceText)
at RazorLight.Compilation.RoslynCompilationService.CreateCompilation(String compilationContent, String assemblyName)
at RazorLight.Compilation.RoslynCompilationService.CompileAndEmit(IGeneratedRazorTemplate razorTemplate)
at RazorLight.Compilation.RazorTemplateCompiler.CompileAndEmit(RazorLightProjectItem projectItem)
at RazorLight.Compilation.RazorTemplateCompiler.OnCacheMissAsync(String templateKey)
--- End of stack trace from previous location ---
at RazorLight.EngineHandler.CompileTemplateAsync(String key)
at RazorLight.EngineHandler.CompileRenderAsync[T](String key, T model, ExpandoObject viewBag)
at MyApplication.MyTemplateParser.CompileAsync(TemplateDto templateDto)
...

If I set PublishSingleFile to False in the Publish Profile, then the error disappears:

<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121. 
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    ...
    <PublishSingleFile>False</PublishSingleFile>
    ...
  </PropertyGroup>
</Project>

Additional information

* OS: Windows Server 2012, IIS version 8.5

* Platform .NET 5.0

* RazorLight version 2.0.0-rc.3

* Are you using the OFFICIAL RazorLight package? Yes

* Visual Studio version: Professional 2019 version 16.8.1.

@marcosdimitrio : You need to add the following into a <PropertyGroup> your csproj-file:

<PreserveCompilationContext>true</PreserveCompilationContext>

Unfortunately that will not help you fix all errors but the one you're currently encountering. See this for details.

b0wter commented 3 years ago

I've done some more digging an am not sure that there is anything this project can do.

RazorLight.Compilation.RoslynCompilationService.GetDependencyContextCompilationOptions

calls

Microsoft.Extensions.DependencyModel.DependencyContext.Load

which calls

Microsoft.Extensions.DependencyModel.DependencyContextLoader.GetDepsJsonPath

That method calls

string assemblyLocation = assembly.Location;

which will always set null because there is no meaningful value to set in a single-file bundle as it can no longer point to a filename. (See the file here) Since no valid value is set the code falls back to calling assembly.CodeBase which suffers the same problem but will raise an exception instead of returning null.

marcosdimitrio commented 3 years ago

@marcosdimitrio : You need to add the following into a <PropertyGroup> your csproj-file:

<PreserveCompilationContext>true</PreserveCompilationContext>

Unfortunately that will not help you fix all errors but the one you're currently encountering. See this for details.

I did include it in both projects (webapi and razorlight project), it only worked when PublishSingleFile is set to false. When I set PublishSingleFile to true it stops working.

toddams commented 3 years ago

RazorLight indeed does not work in a single-file bundle yet. This is relatively new feature and nobody did any work to support that. But it should be supported, imo

toddams commented 3 years ago

https://github.com/dotnet/runtime/issues/35493

FLAMESpl commented 2 years ago

Hi @toddams, is there any work going on in the matter of supporting single-file bundles?

akhanalcs commented 10 months ago

Any update on this? I'm affected by this issue.