当我在没有 EditHistory 成员的情况下渲染我的模板时,这是有效的。但是,当我添加应用程序中的附加成员时,出现异常 Could not load file or assembly 'Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Models 是包含 ContentModel、EditHistory 和 UserDetail 的项目。
public class ContentModel
{
public string Html { get; set; }
public string Title { get; set; }
public EditHistory History { get; set; }
}
public class EditHistory
{
public IReadOnlyCollection<UserDetail> Authors { get; set; }
}
public class UserDetail
{
public string Name { get; set; }
public string EmailAddress { get; set; }
}
我将 ContentModel 包装在 RazorDynamicObject 中,如下所示:
Razor.Run("default.cshtml", typeof(ContentModel), RazorDynamicObject.Create(cm));
如上所述,它无需
EditHistory
即可工作存在,但在存在时失败。沙箱按照在 https://antaris.github.io/RazorEngine/Isolation.html 上的完成方式逐字设置。
如何让它与复杂的自定义类型一起工作?
在 ASP.NET 下运行。
编辑
我已经创建了我面临的问题的最小复制。它在 https://github.com/knightmeister/RazorEngineIssue .如果包恢复失败,手动
install-package razorengine
.
最佳答案
首先;我从来没能让你的 GitHub 代码运行起来。以下是我自己的复现代码。
我认为你得到了无法加载文件或程序集异常,因为当你设置沙箱 AppDomain 时,你正在设置:
adSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
这在 ASP.NET 中不起作用,因为程序集位于
bin
中。子文件夹。要解决这个问题,只需执行以下操作:adSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase
+ "\\bin";
但是,ASP.NET 默认会shadow copy assemblies .因此,仅进行此更改可能会导致另一个异常:
ArgumentException: Object type cannot be converted to target type.
这是因为在默认应用程序域和沙箱中加载的程序集之间存在混淆。默认应用程序域中的那些位于临时卷影副本位置,而沙箱中的那些位于 Web 应用程序根目录的 bin 文件夹中。
解决此问题的最简单方法是通过在
<system.web>
下添加以下行来禁用卷影复制在您的 Web.config 中:<hostingEnvironment shadowCopyBinAssemblies="false"/>
此外;我认为跳过使用
RazorDynamicObject
更好也更容易而是用 [Serializable]
标记您的模型.事实上我从来没有收到过 RazorDynamicObject
好好工作。这个答案的其余部分总结了我为得出这个结论所做的工作
我认为这是由于 RazorEngine 中的错误或限制。 (我不再那么确定了,很可能是影子复制和
RazorDynamicObject
不能一起工作)我花了几个小时试图弄清楚如何让这个工作,但我总是以 RazorEngine 抛出一个安全异常告终。
但是,有一个可能的解决方法:沟
RazorDynamicObject
并将您的模型类标记为可序列化。 [Serializable]
public class ContentModel
{
public string Html { get; set; }
public string Title { get; set; }
public EditHistory History { get; set; }
}
[Serializable]
public class EditHistory
{
public IReadOnlyCollection<UserDetail> Authors { get; set; }
}
[Serializable]
public class UserDetail
{
public string Name { get; set; }
public string EmailAddress { get; set; }
}
并做:
Razor.Run("default.cshtml", typeof(ContentModel), cm); // no RazorDynamicObject
我无法运行您的重现代码,因此我根据您的代码创建了自己的代码:
install-package razorengine
https://github.com/knightmeister/RazorEngineIssue/blob/master/Global.asax.cs
[Serializable]
标记模型. RazorDynamicObject
string template = "@Model.History.Authors[0].EmailAddress";
Authors
在 EditHistory
来自 IReadOnlyCollection<>
至 IReadOnlyList<>
我用生成的代码创建了一个 GIST:
https://gist.github.com/mwikstrom/983c8f61eb10ff1e915a
这对我有用。它打印
hello@world.com
正如它应该的那样。默认情况下,ASP.NET 将影子复制程序集,这将导致沙盒的其他问题。
要使其在 ASP.NET 下工作,您必须进行以下更改:
<system.web>
下添加以下内容来禁用 ASP.NET 卷影复制在您的 Web.config 文件中:<hostingEnvironment shadowCopyBinAssemblies="false"/>
\bin
到沙箱的应用程序基本路径。所以在 createRazorSandbox(...)
做:adSetup.ApplicationBase =
AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "\\bin";
我已经测试过了,它工作得很好。我的测试项目很简单:
install-package razorengine
<hostingEnvironment shadowCopyBinAssemblies="false"/>
在 Web.config 中。 Global.asax.cs
:https://gist.github.com/mwikstrom/ea2b90fd0d306ba3498c
这里列出了其他替代方法(除了禁用卷影复制):
https://github.com/Antaris/RazorEngine/issues/224
关于asp.net - 孤立的 RazorEngine 无法将模型传递到不同的 AppDomain,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34058426/