当前位置:  开发笔记 > 后端 > 正文

孤立的RazorEngine无法将模型传递给不同的AppDomain

如何解决《孤立的RazorEngine无法将模型传递给不同的AppDomain》经验,为你挑选了1个好方法。

当我在没有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 Authors { get; set; }
}

public class UserDetail
{
    public string Name { get; set; }
    public string EmailAddress { get; set; }
}

我在一个RazorDynamicObject中包装ContentModel,如下所示: 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.



1> Mårten Wikst..:

首先; 我从未能够运行您的GitHub代码。以下基于我自己的复制代码。

我认为您将无法加载文件或程序集例外,因为在设置沙箱AppDomain时,您需要进行以下设置:

adSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

这在ASP.NET中不起作用,因为程序集位于bin子文件夹中。要解决此问题,只需执行以下操作即可:

adSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase 
                          + "\\bin";

但是,ASP.NET将默认使用卷影复制程序集。因此,仅执行此更改可能会导致另一个异常:

ArgumentException:无法将对象类型转换为目标类型。

这是因为默认应用程序域中加载的程序集与沙箱之间存在混淆。默认应用程序域中的文件位于临时卷影副本位置,沙箱中的文件位于Web应用程序根目录的bin文件夹中。

解决此问题的最简单方法是通过在Web.config中添加以下行来禁用卷影复制:


此外; 我认为跳过使用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 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

我无法运行您的repro代码,因此我根据您的代码创建了自己的代码:

    创建一个新的控制台应用程序(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";
    

    此外,为了使该模板的工作,改变AuthorsEditHistoryIReadOnlyCollection<>IReadOnlyList<>

我用生成的代码创建了一个GIST:https :
//gist.github.com/mwikstrom/983c8f61eb10ff1e915a

这对我有用。它会hello@world.com按原样打印。


默认情况下,ASP.NET将对影子程序集进行阴影处理,这将导致沙箱的其他问题。

为了使它在ASP.NET下工作,您必须进行以下更改:

    通过在Web.config文件中添加以下内容来禁用ASP.NET阴影复制:

    
    

    附加\bin到沙盒的应用程序基本路径。这样createRazorSandbox(...)做:

    adSetup.ApplicationBase = 
        AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "\\bin";
    

我已经对此进行了测试,并且效果很好。我的测试项目很简单:

一个空的ASP.NET Web应用程序(使用Visual Studio创建),具有 install-package razorengine

在Web.config中。

以下内容Global.asax.cs

https://gist.github.com/mwikstrom/ea2b90fd0d306ba3498c


此处列出了其他替代方法(除了禁用卷影复制):

https://github.com/Antaris/RazorEngine/issues/224

推荐阅读
跟我搞对象吧
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有