diff --git a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/targets/Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.targets b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/targets/Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.targets index f12a6463918d..41beb9d60429 100644 --- a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/targets/Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.targets +++ b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/targets/Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.targets @@ -10,5 +10,8 @@ $(RazorUpToDateReloadFileTypes.Replace('.cshtml', '')) false + + + true diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/AllowedChildTagDescriptor.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/AllowedChildTagDescriptor.cs index 84a83b3e8c76..3e33f1230018 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/AllowedChildTagDescriptor.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/AllowedChildTagDescriptor.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorCodeGenerationOptionsBuilder.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorCodeGenerationOptionsBuilder.cs index 1422b410ff41..2d16ab6b5ab8 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorCodeGenerationOptionsBuilder.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorCodeGenerationOptionsBuilder.cs @@ -52,7 +52,10 @@ public override RazorCodeGenerationOptions Build() SuppressMetadataAttributes, SuppressPrimaryMethodBody, SuppressNullabilityEnforcement, - OmitMinimizedComponentAttributeValues); + OmitMinimizedComponentAttributeValues) + { + SuppressMetadataSourceChecksumAttributes = SuppressMetadataSourceChecksumAttributes, + }; } public override void SetDesignTime(bool designTime) diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/MetadataAttributePass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/MetadataAttributePass.cs index 91bc9ec7b4e4..4ae8cad42c51 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/MetadataAttributePass.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/MetadataAttributePass.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -92,6 +92,12 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentInte return; } + if (documentNode.Options.SuppressMetadataSourceChecksumAttributes) + { + // Checksum attributes are turned off (or options not populated), nothing to do. + return; + } + // Checksum of the main source var checksum = codeDocument.Source.GetChecksum(); var checksumAlgorithm = codeDocument.Source.GetChecksumAlgorithm(); diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptions.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptions.cs index b481dfeb07a6..0bd804a21d53 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptions.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptions.cs @@ -107,6 +107,15 @@ public static RazorCodeGenerationOptions CreateDesignTime(Action public virtual bool SuppressMetadataAttributes { get; protected set; } + /// + /// Gets a value that indicates whether to suppress the RazorSourceChecksumAttribute. + /// + /// Used by default in .NET 6 apps since including a type-level attribute that changes on every + /// edit are treated as rude edits by hot reload. + /// + /// + internal bool SuppressMetadataSourceChecksumAttributes { get; set; } + /// /// Gets or sets a value that determines if an empty body is generated for the primary method. /// diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptionsBuilder.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptionsBuilder.cs index 48d725b6145f..d8896d3050d5 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptionsBuilder.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorCodeGenerationOptionsBuilder.cs @@ -49,6 +49,15 @@ public abstract class RazorCodeGenerationOptionsBuilder /// public virtual bool SuppressMetadataAttributes { get; set; } + /// + /// Gets a value that indicates whether to suppress the RazorSourceChecksumAttribute. + /// + /// Used by default in .NET 6 apps since including a type-level attribute that changes on every + /// edit are treated as rude edits by hot reload. + /// + /// + internal bool SuppressMetadataSourceChecksumAttributes { get; set; } + /// /// Gets or sets a value that determines if an empty body is generated for the primary method. /// diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Extensions/MetadataAttributePassTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Extensions/MetadataAttributePassTest.cs index db50c00268fc..fa911f58d17c 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Extensions/MetadataAttributePassTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Extensions/MetadataAttributePassTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Razor.Language.Components; @@ -381,6 +381,60 @@ public void Execute_HasRequiredInfo_AndImport_AddsItemAndSourceChecksum() Assert.Equal("/Foo/Import.cshtml", checksum.Identifier); } + [Fact] + public void Execute_SuppressMetadataSourceChecksumAttributes_DoesNotGenerateSourceChecksumAttributes() + { + // Arrange + var engine = CreateEngine(); + var pass = new MetadataAttributePass() + { + Engine = engine, + }; + + var sourceDocument = TestRazorSourceDocument.Create("", new RazorSourceDocumentProperties(null, "Foo\\Bar.cshtml")); + var import = TestRazorSourceDocument.Create("@using System", new RazorSourceDocumentProperties(null, "Foo\\Import.cshtml")); + var codeDocument = RazorCodeDocument.Create(sourceDocument, new[] { import, }); + + var irDocument = new DocumentIntermediateNode() + { + DocumentKind = "test", + Options = RazorCodeGenerationOptions.Create(o => o.SuppressMetadataSourceChecksumAttributes = true), + }; + var builder = IntermediateNodeBuilder.Create(irDocument); + var @namespace = new NamespaceDeclarationIntermediateNode + { + Annotations = + { + [CommonAnnotations.PrimaryNamespace] = CommonAnnotations.PrimaryNamespace, + }, + Content = "Some.Namespace" + }; + builder.Push(@namespace); + var @class = new ClassDeclarationIntermediateNode + { + Annotations = + { + [CommonAnnotations.PrimaryClass] = CommonAnnotations.PrimaryClass, + }, + ClassName = "Test", + }; + builder.Add(@class); + + // Act + pass.Execute(codeDocument, irDocument); + + // Assert + Assert.Equal(2, irDocument.Children.Count); + + var item = Assert.IsType(irDocument.Children[0]); + Assert.Equal("/Foo/Bar.cshtml", item.Identifier); + Assert.Equal("test", item.Kind); + Assert.Equal("Some.Namespace.Test", item.TypeName); + + var child = Assert.Single(@namespace.Children); + Assert.IsType(child); + } + private static RazorEngine CreateEngine() { return RazorProjectEngine.Create(b =>