我有一个使用RazorEngine生成电子邮件的类库。 RazorEngine使用Mvc。 我在我的库类中引用了System.Web.Mvc,将其设置为copy local,它存在于Bin文件夹中。但是我仍然得到这个例外。
我实现它的唯一方法是在调用RazorEngine之前实际调用Mvc命名空间中的某些内容,例如MvcHtmlString test = new MvcHtmlString("test");
(找到解决方案here)
我想这不是世界末日,但我仍然想解决这个问题(或者至少了解是什么导致了这个问题)。干杯
答案 0 :(得分:3)
好的,所以我能够将问题归结为以下问题: 您有类似自托管的WebAPI /控制台应用程序,并希望使用Razor 创建HTML页面。那些Razor模板使用Sytem.Web.WebPages中的一些类 或System.Web.Mvc等,它们捆绑在它们自己的程序集中。
但是这些类在视图中仅使用 。在调试模式下启动时,您将看到 运行时不加载这些程序集,无论它们是否已添加到项目中 参考与否。在编译剃刀文件时,编译器只会看到命名空间 从加载的程序集中,您可以获得那些X-not-found异常。你将不得不加载所需的 手动组装(并确保找到兼容的版本)。
我们有一个layout.cshtml和一个index.cshtml。我们使用一些HTML帮助函数来创建表单。 layout.cshtml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<div class="main-content">
@RenderBody()
</div>
</body>
</html>
index.cshtml:
@using System.Web.Mvc;
@{
Layout = "layout";
}
<div class="box-body">
<h1>Hello!</h1>
<p>
Got Html? @MvcHtmlString.Create("<b>FooBarBaz</b>")
</p>
</div>
解析剃刀文件并处理HTML输出的源代码。为简单起见 假设所有文件都在可执行文件附近;您可能需要适应您的存储结构:
//load required assembly. By using the short name here the runtime uses
//the the first one that matches. See MSDN for further information
System.Reflection.Assembly.Load("System.Web.Mvc");
//cache the template before the actual page to avoid a null reference exception
RazorEngine.Razor.GetTemplate(File.ReadAllText("layout.cshtml"), "layout");
var result = RazorEngine.Razor.Parse(File.ReadAllText("index.cshtml"));
Console.Write(result);
然后,您需要将程序集添加到项目中(在此示例中可以通过nuget,Microsoft.AspNet.Mvc),也可以手动添加引用(如果未自动添加)。这样就可以将(希望)正确的版本与可执行文件一起复制。
ASP.Net MVC视图(例如@Html)中几乎所有可用的东西都是注入的对象 ASP.NET管道,因此在直接使用Razor时不可用。 (我不知道是否或如何 除了模型之外,还可以将对象传递给Razor)所以大多数类和函数都是如此 从System.Web.Mvc或System.Web.WebPages命名空间可能无法访问 (不重构ASP.NET的部分)。
使用过的@Layout和@RenderBody()通常也是一些ASP.NET助手。但是因为它们很常见,所以作者似乎在RazorEngine解析器中手动重新创建了它们的功能。
答案 1 :(得分:1)
RazorEngine有一个班级CompilerServicesUtility
。这负责在编译视图时加载和制作程序集。它默认返回当前AppDomain中加载的所有程序集。
当您实例化该程序集中的任何类时,程序集将自动加载到AppDomain中,这就是在调用RazorEngine之前实例化MvcHtmlString test = new MvcHtmlString("test");
的原因。
对于查看代码的人来说,这有点不直观,但另一种确保Razor编译并且您可以使用MvcHtmlString
的方法是将System.Web
和System.Web.Mvc
程序集加载到在执行/编译视图之前使用AppDomain.Current.Load("<assemblyname>")
的当前AppDomain。当然,您可以指定配置文件中所需的程序集列表,并以动态方式加载它。