I have a very simple code sample where I am trying to include a razor template in a loop, but it does not work. Please, observe:
C:\temp\test> dir
Directory: C:\temp\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 7/19/2022 12:23 AM 174 FullMessage.cshtml
-a---- 7/19/2022 12:41 AM 17 MessageItem.cshtml
-a---- 7/19/2022 1:02 AM 1462 Program.cs
-a---- 7/19/2022 12:54 AM 592 Test.csproj
The main code is in Program.cs:
#pragma warning disable CS8619
#pragma warning disable CS8604
#pragma warning disable CS8622
using RazorLight;
var engine = new RazorLightEngineBuilder()
.UseFileSystemProject(Directory.GetCurrentDirectory())
.UseMemoryCachingProvider()
.Build();
int? index = null;
string templateFilePath = "FullMessage.cshtml";
if (args.Length > 0)
{
index = int.Parse(args[0]);
templateFilePath = "MessageItem.cshtml";
}
var list = new[]
{
new
{
Name = "John"
},
new
{
Name = "Jane"
}
};
object model = list;
if (index.HasValue)
{
model = list[index.Value];
Console.WriteLine("Expected to get " list[index.Value].Name);
}
else
{
foreach (var item in list)
{
Console.WriteLine("Expected to get " item.Name);
}
}
Console.WriteLine(engine.CompileRenderAsync(Path.GetFileName(templateFilePath), model).GetAwaiter().GetResult());
The other files are much smaller and are listed at the end of this question.
So when I run it with 0 or 1, the code renders the first or the second item in the list provided in Input.json:
Build
C:\temp\test> dotnet build
Microsoft (R) Build Engine version 17.2.0 41abc5629 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
Restored C:\temp\test\Test.csproj (in 342 ms).
Test -> C:\temp\test\bin\Debug\net6.0\Test.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:03.36
Run
C:\temp\test> .\bin\Debug\net6.0\Test.exe 0
Expected to get John
Name: John
C:\temp\test> .\bin\Debug\net6.0\Test.exe 1
Expected to get Jane
Name: Jane
C:\temp\test>
Everything is good. Now I will run without any parameters. In this case the entire list is rendered while including the item template:
C:\temp\test> .\bin\Debug\net6.0\Test.exe
Expected to get John
Expected to get Jane
Unhandled exception. Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot implicitly convert type 'void' to 'object'
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at RazorLight.CompiledTemplates.GeneratedTemplate.ExecuteAsync() in /FullMessage.cshtml:line 6
at RazorLight.TemplateRenderer.RenderPageCoreAsync(ITemplatePage page, PageContext context)
at RazorLight.TemplateRenderer.RenderPageAsync(ITemplatePage page, PageContext context, Boolean invokeViewStarts)
at RazorLight.TemplateRenderer.RenderAsync(ITemplatePage page)
at RazorLight.EngineHandler.RenderTemplateAsync[T](ITemplatePage templatePage, T model, TextWriter textWriter, ExpandoObject viewBag)
at RazorLight.EngineHandler.RenderTemplateAsync[T](ITemplatePage templatePage, T model, ExpandoObject viewBag)
at RazorLight.EngineHandler.CompileRenderAsync[T](String key, T model, ExpandoObject viewBag)
at Program.<Main>$(String[] args) in C:\Temp\test\Program.cs:line 45
What am I doing wrong?
The rest of the files are below:
FullMessage.cshtml
Count of issues with the source information: @Model.Count
@foreach (dynamic item in Model)
{
<p>
@await IncludeAsync("MessageItem.cshtml", item);
</p>
}
MessageItem.cshtml
Name: @Model.Name
Test.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RazorLight" Version="2.1.0" />
</ItemGroup>
<ItemGroup>
<None Update="*.cshtml" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>
CodePudding user response:
You need to use curly brace in IncludeAsync
call in FullMessage.cshtml.
@{await IncludeAsync("MessageItem.cshtml", item);}