C# RazorEngine 3.4抛出System.ArgumentException:使用缓存的@Layout和不同的模型

C# RazorEngine 3.4抛出System.ArgumentException:使用缓存的@Layout和不同的模型,c#,unit-testing,razorengine,C#,Unit Testing,Razorengine,我对RazorEngine 3.4缓存有问题。我有一些电子邮件模板,每个模板都有相同的@Layout,但不同的型号。它可以正常工作,直到我尝试使用我读取的不使用缓存的缓存:“将导致可怕的性能和内存泄漏” 所以我打开了它。这很简单,但导致了一个问题:\u Layout.cshtml也与第一个模型类型一起缓存,当我尝试用不同的模型解析另一个模板时,它将抛出一个异常:“System.ArgumentException:类型为“…model1…”的对象无法转换为类型“…model2…”。 我在“Isol

我对RazorEngine 3.4缓存有问题。我有一些电子邮件模板,每个模板都有相同的
@Layout
,但不同的
型号。它可以正常工作,直到我尝试使用我读取的不使用缓存的缓存:
“将导致可怕的性能和内存泄漏”

所以我打开了它。这很简单,但导致了一个问题:
\u Layout.cshtml
也与第一个模型类型一起缓存,当我尝试用不同的模型解析另一个模板时,它将抛出一个异常:
“System.ArgumentException:类型为“…model1…”的对象无法转换为类型“…model2…”。

我在“IsolatedTemplateServiceTestFixture.cs”中编写了两个单元测试来说明问题。第一个通过,但第二个失败,因为
TemplateService.SetModelExplicit()
函数想要为
布局设置具有不同
Model
类型的template.Model属性

private Mock<ITemplateResolver> _templateResolver;

    [Test]
    public void IsolatedTemplateService_CanParseTemplateWithLayout_WithOneSerializableModels_UseCache()
    {
        _templateResolver = new Mock<ITemplateResolver>();
        var config = new TemplateServiceConfiguration()
        {
            Resolver = _templateResolver.Object
        };

        using (var service = new TemplateService(config))
        {
            _templateResolver.Setup(i => i.Resolve("test")).Returns("<html>@RenderBody()</html>");

            const string template = @"@{Layout=""test"";}<h1>Hello @Model.Item1</h1>";
            const string expected = "<html><h1>Hello World</h1></html>";

            var model = new Tuple<string>("World");
            string result = service.Parse(template, model, null, "C1");
            string result2 = service.Parse(template, model, null, "C1");

            Assert.That(result == expected, "Result does not match expected: " + result);
            Assert.That(result2 == expected, "Result does not match expected: " + result2);
        }
    }

    [Test]
    public void IsolatedTemplateService_CanParseTemplateWithLayout_WithDifferentSerializableModels_UseCache()
    {
        _templateResolver = new Mock<ITemplateResolver>();
        var config = new TemplateServiceConfiguration()
        {
            Resolver = _templateResolver.Object
        };

        using (var service = new TemplateService(config))
        {
            _templateResolver.Setup(i => i.Resolve("test")).Returns("<html>@RenderBody()</html>");

            const string template = @"@{Layout=""test"";}<h1>Hello @Model.Item1</h1>";
            const string expected = "<html><h1>Hello World</h1></html>";

            var model = new Tuple<string>("World");
            string result = service.Parse(template, model, null, "C1");
            string result2 = service.Parse(template, model, null, "C1");

            const string template2 = @"@{Layout=""test"";}<h1>Hello2 @Model.Item1</h1>";
            const string expected2 = "<html><h1>Hello2 123</h1></html>";
            var model2 = new Tuple<int>(123);

            string result3 = service.Parse(template2, model2, null, "C2");

            Assert.That(result == expected, "Result does not match expected: " + result);
            Assert.That(result2 == expected, "Result does not match expected: " + result2);

            Assert.That(result3 == expected2, "Result does not match expected: " + result3);
        }
    }
private Mock\u templateResolver;
[测试]
public void IsolatedTemplateService_可以使用Layout_和OneSerializableModels_UseCache()解析模板
{
_templateResolver=新建模拟();
var config=new TemplateServiceConfiguration()
{
解析器=_templateResolver.Object
};
使用(var服务=新模板服务(配置))
{
_Setup(i=>i.Resolve(“test”)。返回(“@RenderBody()”);
常量字符串模板=@“{Layout=”“test”“;}Hello@Model.Item1”;
应为常量字符串=“Hello World”;
var模型=新元组(“世界”);
stringresult=service.Parse(模板,模型,null,“C1”);
stringresult2=service.Parse(模板,模型,null,“C1”);
Assert.That(result==expected,“result与expected:+result不匹配”);
Assert.That(result2==expected,“结果与expected不匹配:”+result2);
}
}
[测试]
public void IsolatedTemplateService_可以使用布局分析TemplateWith布局_使用不同的序列化模型_UseCache()
{
_templateResolver=新建模拟();
var config=new TemplateServiceConfiguration()
{
解析器=_templateResolver.Object
};
使用(var服务=新模板服务(配置))
{
_Setup(i=>i.Resolve(“test”)。返回(“@RenderBody()”);
常量字符串模板=@“{Layout=”“test”“;}Hello@Model.Item1”;
应为常量字符串=“Hello World”;
var模型=新元组(“世界”);
stringresult=service.Parse(模板,模型,null,“C1”);
stringresult2=service.Parse(模板,模型,null,“C1”);
常量字符串template2=@“{Layout=”“test”“;}Hello2@Model.Item1”;
const string expected2=“Hello2 123”;
var model2=新元组(123);
字符串result3=service.Parse(template2,model2,null,“C2”);
Assert.That(result==expected,“result与expected:+result不匹配”);
Assert.That(result2==expected,“结果与expected不匹配:”+result2);
Assert.That(result3==expected2,“结果与预期不匹配:”+result3);
}
}
我的问题是:有人有同样的问题吗?在它被修复之前,有什么“好”的解决方法(如果真的发生了)

更新:


使用最新版本(目前为v.3.10),两项测试均通过。因此,问题得到了解决。

在RazorEngine中,布局具有固定的类型,即使您没有在其中声明模型。第一次通过编译模板编译布局时,模板的模型类型也将成为布局的类型。正如您所注意到的,当您尝试编译另一个具有不同类型的模板时,这将发生冲突

您可以通过声明布局动态的模型类型来解决这个问题,即
@model dynamic


这应该能奏效。实际模板不需要更改。

寻求调试帮助的问题(“为什么此代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现此问题所需的最短代码。一个链接很好,但仅仅是希望每个人都能回答这个问题,然后链接到另一个网站,这意味着当这个链接消失后,这个问题将毫无用处。也许不值得尝试与之抗争。只需创建一组视图,每个模型一个。但是使用一个“大”模型,为15个模板创建大量属性并不酷。另一个开发人员不知道必须为特定模板设置哪个。我报告了这个问题,但还没有答案。也许我会创建一个拉请求并自己修复它…请注意,现在在最新的RazorEngine版本中“只起作用”。嗨,谢谢,它起作用了。但是我读到它在高负载下有一些问题,可能是ViewBag是更好的解决方案……ViewBag对我来说似乎是一个非常糟糕的解决方案,因为在视图中没有强类型模型的好处。事实上,我看到了您链接到的问题,并忽略了它,但现在您再次提到它,我们的项目中可能存在相同的问题。我们的应用程序每天最多只发送几百封电子邮件,但它确实在几周内耗尽了内存。我怀疑有一些COM调用,但无法通过负载测试确定。也许我找错地方了。我可能会运行不同的负载测试。