RazorEngine 3.7.7 - 编译缓存模板时出错
RazorEngine 3.7.7 - Error when compiling a cached template
我正在尝试解决我们最近在使用 RazorEngine 3.7.5 及更高版本(尝试过 3.7.7)时遇到的问题
异常:
System.ArgumentException: Please either set a template manager to templates or add the template 'MySolution.Billing.Templates.Layout.cshtml'!
尝试使用 Engine.Razor.Compile 方法缓存模板时发生。
public void AddTemplate(string templateName, string source)
{
Engine.Razor.AddTemplate(templateName, source);
}
public void CacheTemplate(string templateName, Type type)
{
var templateKey = new NameOnlyTemplateKey(templateName, ResolveType.Layout, null);
Engine.Razor.Compile(templateKey, type);
}
PreloadTemplates 方法在使用 StructureMap 实例化创建包含它的服务时被调用。每个模板都存储为嵌入式资源并加载到 RazorEngine 缓存中,并在使用 RazorEngine 编译后立即进行编译,以确保所有模板尽快加载。
private void PreloadTemplates()
{
var embeddedResources = Assembly.GetExecutingAssembly().GetManifestResourceNames().Where(x => x.StartsWith("MySolution.Billing.Templates")).ToList();
foreach (var invoiceResource in embeddedResources)
{
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(invoiceResource))
{
using (var reader = new StreamReader(stream))
{
var template = reader.ReadToEnd();
this._templatingService.AddTemplate(invoiceResource, template);
}
}
}
this._templatingService.CacheTemplate("MySolution.Billing.Templates.Header.cshtml", typeof(HeaderModel));
this._templatingService.CacheTemplate("MySolution.Billing.Templates.Layout.cshtml", typeof(LayoutModel));
this._templatingService.CacheTemplate("MySolution.Billing.Templates.Footer.cshtml", null);
}
RazorEngine配置如下
var config = new TemplateServiceConfiguration();
config.CachingProvider = new DefaultCachingProvider(t => { });
config.DisableTempFileLocking = true;
我们如何使用 RazorEngine,应用程序的流程
- WCF(发票查询外观)
- Global.asax.cs 注册 StructureMap 注册表
- IInvoiceService(由 StructureMap 实例化以提供 InvoiceService)
- 服务在其构造函数中调用 PreloadTemplates
重现步骤
我们几乎每次都可以通过停止 IIS 并重新启动它并调用 WCF 方法来重现错误。这似乎是回收应用程序池或停止 IIS 的问题,因为在 WCF 具有 "warmed up".
后错误不会返回
总算自己找到答案了
我修改了我的 TemplatingService class 如下
public class TemplatingService : ITemplatingService
{
private readonly IRazorEngineService _razorEngineService;
public TemplatingService(Assembly assembly, string templatesNamespace)
{
var config = new TemplateServiceConfiguration();
config.TemplateManager = new EmbeddedResourceTemplateService(assembly, templatesNamespace);
#if DEBUG
config.Debug = true;
#endif
this._razorEngineService = RazorEngineService.Create(config);
}
public void CacheTemplate(string templateName, Type type)
{
var templateKey = new NameOnlyTemplateKey(templateName, ResolveType.Layout, null);
this._razorEngineService.Compile(templateKey, type);
}
public string RunTemplate(string templateName, Type type, object model, IDictionary<string, object> dynamicViewBag = null)
{
var templateKey = new NameOnlyTemplateKey(templateName, ResolveType.Layout, null);
return this._razorEngineService.RunCompile(templateKey, type, model, dynamicViewBag != null ? new DynamicViewBag(dynamicViewBag) : null);
}
}
我开始使用官方网站上的 TemplatingManager:RazorEngine string layouts and sections?,它似乎成功了。
this.For<ITemplatingService>()
.Singleton()
.Add<TemplatingService>()
.Named("invoiceTemplates")
.Ctor<Assembly>("assembly").Is(billingDocumentGeneratorAssembly)
.Ctor<string>("templatesNamespace").Is("MyBillingNamespace.DocumentGenerator.Invoices.Templates");
而且我可以按如下方式使用 TemplatingService
var footerHtml = this._templatingService.RunTemplate("Footer.cshtml", null, null);
var headerHtml = this._templatingService.RunTemplate("Header.cshtml", typeof(AccountStatementHeaderModel), accountStatementModel.Header);
我希望这对其他人有帮助。
我正在尝试解决我们最近在使用 RazorEngine 3.7.5 及更高版本(尝试过 3.7.7)时遇到的问题
异常:
System.ArgumentException: Please either set a template manager to templates or add the template 'MySolution.Billing.Templates.Layout.cshtml'!
尝试使用 Engine.Razor.Compile 方法缓存模板时发生。
public void AddTemplate(string templateName, string source)
{
Engine.Razor.AddTemplate(templateName, source);
}
public void CacheTemplate(string templateName, Type type)
{
var templateKey = new NameOnlyTemplateKey(templateName, ResolveType.Layout, null);
Engine.Razor.Compile(templateKey, type);
}
PreloadTemplates 方法在使用 StructureMap 实例化创建包含它的服务时被调用。每个模板都存储为嵌入式资源并加载到 RazorEngine 缓存中,并在使用 RazorEngine 编译后立即进行编译,以确保所有模板尽快加载。
private void PreloadTemplates()
{
var embeddedResources = Assembly.GetExecutingAssembly().GetManifestResourceNames().Where(x => x.StartsWith("MySolution.Billing.Templates")).ToList();
foreach (var invoiceResource in embeddedResources)
{
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(invoiceResource))
{
using (var reader = new StreamReader(stream))
{
var template = reader.ReadToEnd();
this._templatingService.AddTemplate(invoiceResource, template);
}
}
}
this._templatingService.CacheTemplate("MySolution.Billing.Templates.Header.cshtml", typeof(HeaderModel));
this._templatingService.CacheTemplate("MySolution.Billing.Templates.Layout.cshtml", typeof(LayoutModel));
this._templatingService.CacheTemplate("MySolution.Billing.Templates.Footer.cshtml", null);
}
RazorEngine配置如下
var config = new TemplateServiceConfiguration();
config.CachingProvider = new DefaultCachingProvider(t => { });
config.DisableTempFileLocking = true;
我们如何使用 RazorEngine,应用程序的流程
- WCF(发票查询外观)
- Global.asax.cs 注册 StructureMap 注册表
- IInvoiceService(由 StructureMap 实例化以提供 InvoiceService)
- 服务在其构造函数中调用 PreloadTemplates
重现步骤
我们几乎每次都可以通过停止 IIS 并重新启动它并调用 WCF 方法来重现错误。这似乎是回收应用程序池或停止 IIS 的问题,因为在 WCF 具有 "warmed up".
后错误不会返回总算自己找到答案了
我修改了我的 TemplatingService class 如下
public class TemplatingService : ITemplatingService
{
private readonly IRazorEngineService _razorEngineService;
public TemplatingService(Assembly assembly, string templatesNamespace)
{
var config = new TemplateServiceConfiguration();
config.TemplateManager = new EmbeddedResourceTemplateService(assembly, templatesNamespace);
#if DEBUG
config.Debug = true;
#endif
this._razorEngineService = RazorEngineService.Create(config);
}
public void CacheTemplate(string templateName, Type type)
{
var templateKey = new NameOnlyTemplateKey(templateName, ResolveType.Layout, null);
this._razorEngineService.Compile(templateKey, type);
}
public string RunTemplate(string templateName, Type type, object model, IDictionary<string, object> dynamicViewBag = null)
{
var templateKey = new NameOnlyTemplateKey(templateName, ResolveType.Layout, null);
return this._razorEngineService.RunCompile(templateKey, type, model, dynamicViewBag != null ? new DynamicViewBag(dynamicViewBag) : null);
}
}
我开始使用官方网站上的 TemplatingManager:RazorEngine string layouts and sections?,它似乎成功了。
this.For<ITemplatingService>()
.Singleton()
.Add<TemplatingService>()
.Named("invoiceTemplates")
.Ctor<Assembly>("assembly").Is(billingDocumentGeneratorAssembly)
.Ctor<string>("templatesNamespace").Is("MyBillingNamespace.DocumentGenerator.Invoices.Templates");
而且我可以按如下方式使用 TemplatingService
var footerHtml = this._templatingService.RunTemplate("Footer.cshtml", null, null);
var headerHtml = this._templatingService.RunTemplate("Header.cshtml", typeof(AccountStatementHeaderModel), accountStatementModel.Header);
我希望这对其他人有帮助。