I have a solution in which most of the projects are VB.net projects which all target the .NET Framework 4.8. All of those specific projects compile properly and are running in production.
I have added a C# project that targets .net standard 2.0. The primary reason for this particular project is to create a component that can process razor templates (given a model of course) in order to create output files using the RazorLight_wik8wz nuget package (I don't really care which package I use so long as I can render a razor template in memory because the output generated by the model/template pair may be persisted in different places in different cases).
In theory, and based on my understanding, I should be able to reference and use a .net standard 2.0 library project from my other .net framework 4.8 projects. However, I can't seem to get this to work (even though everything compiles and runs).
I've tried several different packages based on RazorLight--but I get similar results when I try to use them. I'm simply not sure if I'm encountering a bug or if I'm not doing something properly.
The C# project is named "JobOutputGenerator." I have added the nuget package called "RazorLight_wik8wz" and created an object called JobOutput that currently looks like this:
using System.Threading.Tasks;
using RazorLight;
public class JobOutput
{
public static async Task<byte[]> CreateOutputAsync(string RazorTemplate, object Model)
{
RazorLightEngine engine = new RazorLightEngineBuilder().UseMemoryCachingProvider().Build();
return System.Text.Encoding.ASCII.GetBytes(await engine.CompileRenderAsync(RazorTemplate.GetHashCode().ToString() + Model.GetHashCode().ToString(), RazorTemplate, Model));
}
}
I have created another project called "TesterApp" which is a VB.NET project that targets .NET Framework 4.8. It is a simple windows form project that references JobOutputGenerator.
I have a button that does the following:
Private Sub btnRenderSample_Click(sender As Object, e As EventArgs) Handles btnRenderSample.Click
Dim template As String = "Hello @Model.Name"
Dim Model1 = New With {.Name = "John Doe"}
Dim bytesTask = JobOutput.CreateOutputAsync(template, Model1)
Dim str = System.Text.Encoding.ASCII.GetString(bytesTask.Result)
MsgBox(str)
End Sub
When I launch the TesterApp in debug mode in Visual Studio, all projects compile just fine, and then when I click my sample button, Visual Studio breaks on the line (while highlighted in green):
Dim bytesTask = JobOutput.CreateOutputAsync(template, Model1)
with a box that is titled "Exception Unhandled" that says:
System.IO.FileNotFoundException: 'Could not load file or assembly 'RazorLight, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.'
I have run fuslogvw and TesterApp has no problem locating JobOutputGenerator.dll:
<meta http-equiv="Content-Type" content="charset=unicode-1-1-utf-8"><!-- saved from url=(0015)assemblybinder: --><html><pre>
*** Assembly Binder Log Entry (6/7/2019 @ 9:37:08 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\TesterApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = JobOutputGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = TesterApp.exe
Calling assembly : TesterApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\TesterApp.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/JobOutputGenerator.DLL.
LOG: Assembly download was successful. Attempting setup of file: X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\JobOutputGenerator.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: JobOutputGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: Binding succeeds. Returns assembly from X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\JobOutputGenerator.dll.
LOG: Assembly is loaded in default load context.
</pre></html>
I did, however, find this little "gem" in fuslogvw and I don't know what to do about it:
*** Assembly Binder Log Entry (6/7/2019 @ 9:37:09 AM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\TesterApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = RazorLight, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = TesterApp.exe
Calling assembly : JobOutputGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: X:\Workspaces\SOLUTIONROOTFOLDER\TesterApp\bin\Debug\TesterApp.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/RazorLight.DLL.
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/RazorLight/RazorLight.DLL.
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/RazorLight.EXE.
LOG: Attempting download of new URL file:///X:/Workspaces/SOLUTIONROOTFOLDER/TesterApp/bin/Debug/RazorLight/RazorLight.EXE.
LOG: All probing URLs attempted and failed.
The following is the contents of the JobOutputGenerator.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ILRepack.MSBuild.Task" Version="2.0.1" />
<PackageReference Include="RazorLight_wik8wz" Version="2.0.0" />
</ItemGroup>
<Target Name="ILRepack" AfterTargets="Build">
<PropertyGroup>
<WorkingDirectory>$(MSBuildThisFileDirectory)bin\$(Configuration)\$(TargetFramework)</WorkingDirectory>
</PropertyGroup>
<ILRepack
OutputType="$(OutputType)"
MainAssembly="$(AssemblyName).dll"
OutputAssembly="$(AssemblyName).dll"
InputAssemblies="$(WorkingDirectory)\*.dll"
WilcardInputAssemblies="true"
WorkingDirectory="$(WorkingDirectory)" />
</Target>
</Project>