Recently, a project encountered a problem. In our view, we often encountered some anonymous objects, and then output these objects through RenderPartial.
For example, there are three view indexes. cshtml, Test. cshtml, and Test2.cshtml.
Their hierarchy
Their code is as follows:
Index. cshtml
[Csharp]
@{
Layout = null;
Var obj = new [] {
New {name = "majiang", age = 27 },
New {name = "luyang", age = 26}
};
}
<! DOCTYPE html>
<Html>
<Head>
<Title> Index </title>
</Head>
<Body>
<Div>
@{
<H2> @ (obj. GetType (). Assembly. Location) Html. RenderPartial ("Test", obj );
Html. RenderPartial ("Test2", obj );
}
</Div>
</Body>
</Html>
@{
Layout = null;
Var obj = new [] {
New {name = "majiang", age = 27 },
New {name = "luyang", age = 26}
};
}
<! DOCTYPE html>
<Html>
<Head>
<Title> Index </title>
</Head>
<Body>
<Div>
@{
<H2> @ (obj. GetType (). Assembly. Location) Html. RenderPartial ("Test", obj );
Html. RenderPartial ("Test2", obj );
}
</Div>
</Body>
</Html>
Test. cshtml and Test2.cshtml
[Csharp] view plaincopyprint? @{
Layout = null;
Var obj = this. Model;
Var a = new {name = "majiang", age = 27 };
<H2> @ (a. GetType (). Assembly. Location)
Foreach (var item in obj)
{
<H3> @ item. name <H3> @ item. age }
}
@{
Layout = null;
Var obj = this. Model;
Var a = new {name = "majiang", age = 27 };
<H2> @ (a. GetType (). Assembly. Location)
Foreach (var item in obj)
{
<H3> @ item. name <H3> @ item. age }
}
The following error message is displayed when Test2.cshtml runs:
Why is it true in test and test2 is wrong? The two views only have different paths. Is it true that different paths lead to different dll paths? Let's verify it.
First, modify the code in test2:
@{
Layout = null;
Var obj = this. Model;
Var a = new {name = "majiang", age = 27 };
<H2> @ (a. GetType (). Assembly. Location)
@ * Foreach (var item in obj)
{
<H3> @ item. name <H3> @ item. age }*@
}
Running result
Obviously, test and index are in the same directory, and their generated anonymous types are also in the same dll, while test2 is no longer in this directory, so the generated anonymous types are not in the same dll.
Why? Let's take a look at the source code.
In the public void Render (ViewContext viewContext, TextWriter writer) method of the BuildManagerCompiledView class
Type type = BuildManager. GetCompiledType (ViewPath );
The definition of BuildManager is:
Internal IBuildManager BuildManager {
Get {
If (_ buildManager = null ){
_ BuildManager = new BuildManagerWrapper ();
}
Return _ buildManager;
}
Set {
_ BuildManager = value;
}
}
Let's take a look at the BuildManagerWrapper class.
Internal sealed class BuildManagerWrapper: IBuildManager {
Bool IBuildManager. FileExists (string virtualPath ){
Return BuildManager. GetObjectFactory (virtualPath, false )! = Null;
}
Type IBuildManager. GetCompiledType (string virtualPath ){
Return BuildManager. GetCompiledType (virtualPath );
}
ICollection IBuildManager. GetReferencedAssemblies (){
Return BuildManager. GetReferencedAssemblies ();
}
Stream IBuildManager. ReadCachedFile (string fileName ){
Return BuildManager. ReadCachedFile (fileName );
}
Stream IBuildManager. CreateCachedFile (string fileName ){
Return BuildManager. CreateCachedFile (fileName );
}
}
It seems that the compilation of view depends on the BuildManager of the system. It is not realistic for both the internal class of the Assembly and the sealed class to expand it.
So how can this be solved? Since we cannot allow all views to be dynamically compiled into the same dll, can we compile these views into the current project dll? (It is troublesome to maintain the view because it updates the dll of the project where the view is located.) can this problem be solved? The theory is feasible. Let's try it.
First, let's install
Razor Generator
Second, use NuGet Security Protection PrecompiledMvcViewEngine.
Modify the custom tool in the view attribute to RazorGenerator.
Finally, we restored test2 and finally run the result:
The operation is successful.