0

In my .NET 4.8 Web API application, I take an externally received HTML formatted string and convert it to a .cshtml file using Razor Engine, then append it to my page with JavaScript. I do this using the RazorEngine NuGet package.

I have updated my Web API application to .NET 6 and brought the same functionality to it. However, with the .NET Core version of the same NuGet package, I encountered the following error:

Value cannot be null (type= parameter)

I have also tried the following NuGet packages. But with these packages, I can only run plain C# code with Razor. For example, I cannot use methods like Convert, Decimal, Math:

  • RazorLight
  • RazorEngineCore

What solution can I use for this feature?

0

1 Answer 1

0

I have updated my Web API application to .NET 6 and brought the same functionality to it. However, with the .NET Core version of the same NuGet package, I encountered the following error:

Value cannot be null (type= parameter)

Based on your description and error message I have tried to reproduce your issue.

According to my test, I have followed below steps and both Convert, Decimal, Math features working as expected.

Let't have a look in practice, how I implemented that:

Step 1: Downloaded Nuget Package:

enter image description here

Step 2: Update csproj file:

Make sure you have added <PreserveCompilationContext>true</PreserveCompilationContext> within csproj file in order to get rid of run time error.

My csproj details for your reference:

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <PreserveCompilationContext>true</PreserveCompilationContext>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.4" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
            <PrivateAssets>all</PrivateAssets>
            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
        <PackageReference Include="RazorLight" Version="2.3.1" />
    </ItemGroup>

</Project>

Step 3: Handle your error: Value cannot be null (type= parameter)

I have used following smaple template for testing:

public class RazorTemplateRenderer
{
    private readonly RazorLightEngine _engine;

    public RazorTemplateRenderer()
    {
        _engine = new RazorLightEngineBuilder()
            .UseMemoryCachingProvider()
            .Build();
    }

    public async Task<string> RenderTemplateAsync(string templateContent, object model)
    {
        if (templateContent == null)
        {
            throw new ArgumentNullException(nameof(templateContent));
        }

        if (model == null)
        {
            throw new ArgumentNullException(nameof(model));
        }

        try
        {
            string result = await _engine.CompileRenderStringAsync("templateKey", templateContent, model);
            return result;
        }
        catch (Exception ex)
        {
           
            throw new InvalidOperationException("Failed to render template.", ex);
        }
    }
}   

Step 4: Demo Controller:

public class TemplateController : Controller
{
    private readonly RazorTemplateRenderer _renderer;

    public TemplateController(RazorTemplateRenderer renderer)
    {
        _renderer = renderer;
    }

    [HttpGet]
    public async Task<IActionResult> Render()
    {


        string template = @"
                @using System
                @using CustomerManagementTool.Models
                @model TemplateModel
                <div>
                    <p>Amount: @Model.Amount</p>
                    <p>Rounded Amount: @(Math.Round(Model.Amount, 2))</p>
                    <p>Converted Amount: @(Convert.ToDecimal(Model.Amount))</p>
                </div>";

        var model = new TemplateModel { Amount = 123.456m };
        string result = await _renderer.RenderTemplateAsync(template, model);

        return Content(result, "text/html");
    }
}

Step 5: Service DI in program.cs:

builder.Services.AddSingleton<RazorTemplateRenderer>();

Output:

enter image description here

enter image description here

enter image description here

enter image description here

Note: While I was trying to simulate the scenario, I have also encountered few issues as well. However, the point you should consider, make sure your templete references are correct, in my scenario which are @using System @using CustomerManagementTool.Models @model TemplateModel, also be aware, if you have passed the parameters accordingly. Ensure that all required parameters (templateContent and model) are not null when calling the CompileRenderStringAsync method. Last but not the least, verify that templateContent is a non-null string containing the Razor template markup.

Not the answer you're looking for? Browse other questions tagged or ask your own question.