asp.net - 孤立的 RazorEngine 无法将模型传递到不同的 AppDomain

标签 asp.net .net razorengine isolation

当我在没有 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

我无法运行您的重现代码,因此我根据您的代码创建了自己的代码:
  • 创建新的控制台应用程序 (Visual Studio)
  • 在包管理器控制台中,运行:install-package razorengine
  • 从您的重现复制代码:
  • 25-38 和 43-65 行:
    https://github.com/knightmeister/RazorEngineIssue/blob/master/Global.asax.cs
  • 所有型号来自:https://github.com/knightmeister/RazorEngineIssue/blob/master/Models/Models.cs
  • [Serializable] 标记模型.
  • 删除 RazorDynamicObject
  • 为了确保我们真的可以从作者列表中呈现用户详细信息,请将测试模板更改为:
    string template = "@Model.History.Authors[0].EmailAddress";
    
  • 此外,要使该模板工作,请更改 AuthorsEditHistory来自 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";
    

  • 我已经测试过了,它工作得很好。我的测试项目很简单:
  • 一个空的 ASP.NET Web 应用程序(使用 Visual Studio 创建),带有 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/

    相关文章:

    JavaScript 不适用于 @Html.CheckBoxFor

    ASP.NET MVC 2 EditModel 包含 Id?保护 ID 未被篡改

    javascript - 从代码隐藏错误调用 javascript 函数

    c# - 将文件从 MVC 发布到 WEB API

    c# - LINQ:不同值和合并值

    .net - VB.NET 内存管理

    c# - 我如何创建一个方法类型 bool 并循环控制来决定案例?

    c# - VS2015 在 RazorEngine 模板中看不到 Linq

    c# - 从 html 助手中获取未编码的 html

    生成 HTML 和 Excel 的 ASP.Net Web 服务器控件