0

As part of a Roslyn Analyzer (C#), I would like to access the intermediate model of Razor parser to check the content for project specific coding guidelines.

// Referenced NuGet:
// <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="6.0.36" />
public void Run()
{
    // Create RazorEngine
    string rootDirectoryPath = @"D:\Home-2025\RazorEnginePrototype";
    var fileSystem = RazorProjectFileSystem.Create(rootDirectoryPath);
    RazorConfiguration configuration = RazorConfiguration.Default;

    var engine = RazorProjectEngine.Create(configuration, fileSystem, builder =>
    {
        // Microsoft.AspNetCore.Mvc.Razor.Extensions
        RazorExtensions.Register(builder);
    });
    var razorEngine = engine.Engine;

    // Parse razor file
    string relativeFilePath = @"Views\StartPage.cshtml";
    string filePath = Path.Combine(rootDirectoryPath, relativeFilePath);
    string razorContent = File.ReadAllText(filePath);
    var projectItem = fileSystem.GetItem(relativeFilePath);

    RazorSourceDocumentProperties properties = new RazorSourceDocumentProperties(filePath, relativeFilePath);
    var sourceDocument = RazorSourceDocument.Create(razorContent, properties);
    var codeDocument = RazorCodeDocument.Create(sourceDocument);
    razorEngine.Process(codeDocument);

    // Try access intermediate node => mt is "dynamic"
    DocumentIntermediateNode documentNode = codeDocument.GetDocumentIntermediateNode();
    var mt = ModelDirective.GetModelType(documentNode);

    // Returns generated C# code
    var csDoc = codeDocument.GetCSharpDocument();
    Console.WriteLine(csDoc.GeneratedCode);
}

The content of the StartPage.cshtml:

@model YourNamespace.YourModelClass

<h1>@Model.Property</h1>

The code above generates this C# representation of StartPage.cshtml in csDoc.GeneratedCode (this means that the code above runs the whole Razor-to-C# compilation process, also YourNamespace.YourModelClass is part of the generated code):

#pragma checksum "D:\Home-2025\RazorEnginePrototype\Views\StartPage.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "3ccef06a8a2d010b1de36900769176e1a7c1d2c4"
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCore.Views_StartPage), @"mvc.1.0.view", @"/Views/StartPage.cshtml")]
namespace AspNetCore
{
    #line hidden
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"3ccef06a8a2d010b1de36900769176e1a7c1d2c4", @"/Views/StartPage.cshtml")]
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/StartPage.cshtml")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    public class Views_StartPage : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<YourNamespace.YourModelClass>
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral("\r\n<h1>");
#nullable restore
#line 3 "D:\Home-2025\RazorEnginePrototype\Views\StartPage.cshtml"
Write(Model.Property);

#line default
#line hidden
#nullable disable
            WriteLiteral("</h1>\r\n");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591

Microsoft.AspNetCore.Mvc.Razor.Extensions seems to provide access functions to the intermediate model.

The problem: I would like to access a near-razor-source based intermediate model (containing "@model" nodes or such). But ModelDirective.GetModelType returns "dynamic" (no specific model type).

What am I doing wrong?

I also traversed the tree of IntermediateNode to see if there is some 'model intermediate Node' as part of the tree:

DocumentIntermediateNode
  RazorCompiledItemAttributeIntermediateNode
  NamespaceDeclarationIntermediateNode
    RazorSourceChecksumAttributeIntermediateNode
    RazorCompiledItemMetadataAttributeIntermediateNode
    CreateNewOnMetadataUpdateAttributeIntermediateNode
    ClassDeclarationIntermediateNode
      MethodDeclarationIntermediateNode
        HtmlContentIntermediateNode
          LazyIntermediateToken
          LazyIntermediateToken
          LazyIntermediateToken 
        CSharpExpressionIntermediateNode
          LazyIntermediateToken
        HtmlContentIntermediateNode
          LazyIntermediateToken
          LazyIntermediateToken

Does 'intermediate node' mean that razor parser transforms the intermediate model (replacing nodes by other nodes) instead of enriching it (adding new nodes)?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.