RazorLight: Method 'WriteTo' does not have an implementation
Describe the bug
RazorLight is throwing the following exception when running engine.CompileRenderAsync
System.TypeLoadException: Method 'WriteTo' in type 'RazorLight.Internal.ViewBuffer' from assembly 'RazorLight, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
at RazorLight.TemplateRenderer.RenderPageAsync(ITemplatePage page, PageContext context, Boolean invokeViewStarts)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
To Reproduce It seems like an incompatibility between dependencies, but I couldn’t figure out exactly which one.
Expected behavior
It seems the said WriteTo method in ViewBuffer class is a reference of the interface IHtmlContent, in the assembly Microsoft.AspNetCore.Html.Abstractions v2.1.0. The weird part is that this nuget package is apparently abandoned, the link to the project points to an archived repository, and I expect to see AspNetCore being on version 3.1, not 2.1.
Information (please complete the following information):
- OS: Windows 10
- Platform: Net Core 3.1
- RazorLight version: 2.0.0-rc.3
- Are you using the OFFICIAL RazorLight package? yes
- Visual Studio version: Visual Studio Community 2019 16.10.1 ]
About this issue
- Original URL
- State: open
- Created 3 years ago
- Comments: 41
I think you misunderstood the conversation. It is not possible without dirty loading. Microsoft even said so. They built a plug-in architecture that does not allow safe loading of dynamically loaded plug-ins, including code written by Microsoft. Your only other option is to use out-of-process worker model, because it converts a dynamic plug-in into a static one. Please re-read. Thank you.
@junalmeida Thanks for that info. Based on a quick google search for System.Text.Encodings.Web azure.core error, it looks like if you file an issue with Azure Functions, they will simply close it as “by design” and tell you to use “the worker model”:
Did I ever mention how much I dislike Azure Functions and think they’re a complete waste of everyone’s time? It looks like out-of-process workers fix these problems, though. Unless you want to use durable functions. Then you should probably use the Durable Task Framework as a workaround. - I don’t know if it would be a valid workaround but despite both having the word durable in it, there is nothing in common here between durable azure functions and the durable task framework. The guy who created the Durable Task Framework, @samarabbas, quit Microsoft and is basically selling a “low code” distributed computing framework inspired by the DTF. Durable Tasks are also only C# - whereas Durable Functions is supposed to be language agnostic.
The “worker model” the Microsoft employee refers to is the out-of-process model we just discussed. See: https://github.com/Azure/azure-functions-dotnet-worker
I do think, given Microsoft’s rather funny comments that you can’t upgrade System.Text.Json even one minor patch number without things breaking, that you should not spend any effort on the “in process” model and instead running everything “out of process.” You can see my extended conversation with Microsoft about this, here: https://github.com/dotnet/standard/issues/859#issuecomment-702503596
Basically, we’re in this situation because Microsoft decided binding redirects made customer support extremely difficult, because it exploded the number of library-version interactions that might occur. But, they did not solve the user story binding redirects made so easy to solve, which was a hamfisted DSL for resolving run-time assembly conflicts. As far as I can guess, the reason they don’t want to solve this is it can’t be checked by the compiler, and so it can produce less reliable systems.
BTW, you can actually see Microsoft makes the same point I claim:
https://docs.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide#benefits-of-running-out-of-process
In other words, they’re saying their original in-process architecture was a really bad idea. 😄
When you create a direct dependency, you opt in to roll forward. When you have an indirect dependency, it does not. So I believe we are saying the same thing.
The problem is that Roll Forward is based on the host executable. So you can create your own host and even specify Roll Forward LatestMajor, and it will Roll Forward that. But if you then dynamically load a different DLL version, Roll Forward doesnt know about that. The AssemblyLoadContext is literally just loading whatever DLL you give it. When that Assembly is unique, it will load correctly, but then calling functions in that assembly may fail if it transitively references another DLL with different version than one already in the AssemblyLoadContext.
Hope that is clear.
This is pretty complex stuff and nobody likes to admit how complex Microsoft made this. Unofficially, Microsoft’s preference is people stop using anything that requires reflection/dynamic code loading and instead use C# Source Generators, as that opts in to the upstream gadgetry of MSBuild SDKs calculating the transitive closure of all static dependencies via ProjectReference and PackageReference, Roll Forward technology, etc.