Skip to content

Razor Processing loses @@inject immediately after code block #10811

@seancpeters

Description

@seancpeters

Describe the bug

When processing razor content, if I include an @@inject immediately after a razor code block, the @@inject is missing from the generated code.

To Reproduce

Steps to reproduce the behavior:

I am using the following code to process .cshtml documents, from:
https://github.com/aspnet/Scaffolding/blob/master/src/VS.Web.CG.Templating/RazorTemplating.cs

        public async Task<TemplateResult> RunTemplateAsync(string content,
            dynamic templateModel)
        {
            var fileSystem = RazorProjectFileSystem.Create(Directory.GetCurrentDirectory());
            var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, (builder) =>
            {
                builder.SetCSharpLanguageVersion(LanguageVersion.CSharp5);

                SectionDirective.Register(builder);

                builder.AddTargetExtension(new TemplateTargetExtension()
                {
                    TemplateTypeName = "global::Microsoft.AspNetCore.Mvc.Razor.HelperResult",
                });

                builder.AddDefaultImports(@"
@using System
@using System.Threading.Tasks
");
            });

            var templateItem = new TemplateRazorProjectItem(content);
            var codeDocument = projectEngine.Process(templateItem);
            var generatorResults = codeDocument.GetCSharpDocument();
...

Relevant package versions:

  • Microsoft.AspNetCore.Razor.Language 3.0.0-preview5.19227.1
  • Microsoft.AspNetCore.Razor.Runtime 2.2.0
  • Microsoft.CodeAnalysis.CSharp 3.0.0
  • Microsoft.CodeAnalysis.Razor 3.0.0-preview5.19227.1

When processing this content:

@inherits Microsoft.VisualStudio.Web.CodeGeneration.Templating.RazorTemplateBase
@@inject Injection_1<@Model.UserClass> SignInManager
@{
}
@@inject Injection_2<@Model.UserClass> SignInManager
@@inject Injection_3<@Model.UserClass> SignInManager

@{
}

@@inject Injection_4<@Model.UserClass> SignInManager
@@inject Injection_5<@Model.UserClass> SignInManager

The @@inject statements immediately following the Razor code blocks @{} are ignored. Note that this is a minimal repro, and in my real document, the code blocks are non-empty, but the behavior is the same.

This is the resultant generated code, from generatorResults.GeneratedCode:

#pragma checksum "/Template" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "56db2e49cde5532043b4dbba05681ee4f639a09a"
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(Razor.Template), @"default", @"/Template")]
namespace Razor
{
    #line hidden
    using System;
    using System.Threading.Tasks;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"56db2e49cde5532043b4dbba05681ee4f639a09a", @"/Template")]
    public class Template : Microsoft.VisualStudio.Web.CodeGeneration.Templating.RazorTemplateBase
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral("@inject #pragma checksum "/Template" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "56b89f33448424670b877edfa22c9838a030c798"
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(Razor.Template), @"default", @"/Template")]
namespace Razor
{
    #line hidden
    using System;
    using System.Threading.Tasks;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"56b89f33448424670b877edfa22c9838a030c798", @"/Template")]
    public class Template : Microsoft.VisualStudio.Web.CodeGeneration.Templating.RazorTemplateBase
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral("@inject Injection_1<");
#line 2 "/Template"
                Write(Model.UserClass);

#line default
#line hidden
            WriteLiteral("> SignInManager\n");
            WriteLiteral("\n");
            WriteLiteral("Injection_2<");
#line 5 "/Template"
                Write(Model.UserClass);

#line default
#line hidden
            WriteLiteral("> SignInManager\n");
            WriteLiteral("@inject Injection_3<");
#line 6 "/Template"
                Write(Model.UserClass);

#line default
#line hidden
            WriteLiteral("> SignInManager\n\n");
            WriteLiteral("\n\n");
            WriteLiteral("Injection_4<");
#line 11 "/Template"
                Write(Model.UserClass);

#line default
#line hidden
            WriteLiteral("> SignInManager\n");
            WriteLiteral("@inject Injection_5<");
#line 12 "/Template"
                Write(Model.UserClass);

#line default
#line hidden
            WriteLiteral("> SignInManager\n");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591

Note that there is no @inject preceding Injection_2 or Injection_4, which are the ones immediately following the code blocks.

Expected behavior

All of the @@inject statements should be processed / included.

Additional context

I believe this is a regression from previous versions. The file I noticed this issue with is:
https://github.com/aspnet/Scaffolding/blob/master/src/VS.Web.CG.Mvc/Templates/Identity/Bootstrap4/_LoginPartial.cshtml

This has not changed since August 2018, and prior to the razor changes for 3.x, the @@Inject statements were processed as expected.

Including the output of dotnet --info, but don't think it's relevant here:

c:\Github\WebTools\src\Scaffolding>dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   3.0.100-preview5-011568
 Commit:    b487ff10aa

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.18362
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.0.100-preview5-011568\

Host (useful for support):
  Version: 3.0.0-preview5-27626-15
  Commit:  61f30f5a23

.NET Core SDKs installed:
  1.1.11 [C:\Program Files\dotnet\sdk]
  1.1.12 [C:\Program Files\dotnet\sdk]
  1.1.13 [C:\Program Files\dotnet\sdk]
  1.1.14 [C:\Program Files\dotnet\sdk]
  2.0.0 [C:\Program Files\dotnet\sdk]
  2.1.202 [C:\Program Files\dotnet\sdk]
  2.1.503 [C:\Program Files\dotnet\sdk]
  2.1.504 [C:\Program Files\dotnet\sdk]
  2.1.505 [C:\Program Files\dotnet\sdk]
  2.1.600-preview-009472 [C:\Program Files\dotnet\sdk]
  2.1.600-preview-009497 [C:\Program Files\dotnet\sdk]
  2.1.600 [C:\Program Files\dotnet\sdk]
  2.1.601 [C:\Program Files\dotnet\sdk]
  2.1.602 [C:\Program Files\dotnet\sdk]
  2.1.604 [C:\Program Files\dotnet\sdk]
  2.1.700-preview-009597 [C:\Program Files\dotnet\sdk]
  2.1.700-preview-009601 [C:\Program Files\dotnet\sdk]
  2.1.700-preview-009618 [C:\Program Files\dotnet\sdk]
  2.1.800-preview-009677 [C:\Program Files\dotnet\sdk]
  2.2.103 [C:\Program Files\dotnet\sdk]
  2.2.200-preview-009748 [C:\Program Files\dotnet\sdk]
  2.2.200-preview-009804 [C:\Program Files\dotnet\sdk]
  2.2.200 [C:\Program Files\dotnet\sdk]
  2.2.201 [C:\Program Files\dotnet\sdk]
  2.2.202 [C:\Program Files\dotnet\sdk]
  2.2.204 [C:\Program Files\dotnet\sdk]
  2.2.300-preview-010044 [C:\Program Files\dotnet\sdk]
  2.2.300-preview-010046 [C:\Program Files\dotnet\sdk]
  2.2.300-preview-010050 [C:\Program Files\dotnet\sdk]
  2.2.300-preview-010063 [C:\Program Files\dotnet\sdk]
  2.2.300-preview-010067 [C:\Program Files\dotnet\sdk]
  2.2.400-preview-010195 [C:\Program Files\dotnet\sdk]
  3.0.100-preview-009812 [C:\Program Files\dotnet\sdk]
  3.0.100-preview5-011555 [C:\Program Files\dotnet\sdk]
  3.0.100-preview5-011568 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0-preview5-19227-01 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview5-27626-15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.0-preview5-27626-15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

Metadata

Metadata

Assignees

No one assigned

    Labels

    affected-fewThis issue impacts only small number of customersarea-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templatesbugThis issue describes a behavior which is not expected - a bug.feature-razor.languageseverity-minorThis label is used by an internal tool

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions