Allow _ViewImports to remove default inherited tag helpers.

Additionally simplifying the contract for
ChunkInheritaceUtility\IChunkMerger so we don't have to understand the
order in which CodeTrees appear.
This commit is contained in:
Pranav K 2015-09-17 22:37:31 -07:00
parent b95dcd5f1c
commit f045c6792b
30 changed files with 300 additions and 313 deletions

View File

@ -3,7 +3,6 @@
using System; using System;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Mvc.Razor.Host;
using Microsoft.AspNet.Razor.Chunks; using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives namespace Microsoft.AspNet.Mvc.Razor.Directives
@ -15,33 +14,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
{ {
private const string TModelToken = "<TModel>"; private const string TModelToken = "<TModel>";
/// <summary>
/// Attempts to cast the passed in <see cref="Chunk"/> to type <typeparamref name="TChunk"/> and throws if the
/// cast fails.
/// </summary>
/// <typeparam name="TChunk">The type to cast to.</typeparam>
/// <param name="chunk">The chunk to cast.</param>
/// <returns>The <paramref name="chunk"/> cast to <typeparamref name="TChunk"/>.</returns>
/// <exception cref="ArgumentException"><paramref name="chunk"/> is not an instance of
/// <typeparamref name="TChunk"/>.</exception>
public static TChunk EnsureChunk<TChunk>(Chunk chunk)
where TChunk : Chunk
{
if (chunk == null)
{
throw new ArgumentNullException(nameof(chunk));
}
var chunkOfT = chunk as TChunk;
if (chunkOfT == null)
{
var message = Resources.FormatArgumentMustBeOfType(typeof(TChunk).FullName);
throw new ArgumentException(message, nameof(chunk));
}
return chunkOfT;
}
/// <summary> /// <summary>
/// Returns the <see cref="ModelChunk"/> used to determine the model name for the page generated /// Returns the <see cref="ModelChunk"/> used to determine the model name for the page generated
/// using the specified <paramref name="chunkTree"/> /// using the specified <paramref name="chunkTree"/>

View File

@ -63,6 +63,12 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
/// <param name="pagePath">The path of the page to locate inherited chunks for.</param> /// <param name="pagePath">The path of the page to locate inherited chunks for.</param>
/// <returns>A <see cref="IReadOnlyList{ChunkTreeResult}"/> of parsed <c>_ViewImports</c> /// <returns>A <see cref="IReadOnlyList{ChunkTreeResult}"/> of parsed <c>_ViewImports</c>
/// <see cref="ChunkTree"/>s and their file paths.</returns> /// <see cref="ChunkTree"/>s and their file paths.</returns>
/// <remarks>
/// The resulting <see cref="IReadOnlyList{ChunkTreeResult}"/> is ordered so that the result
/// for a _ViewImport closest to the application root appears first and the _ViewImport
/// closest to the page appears last i.e.
/// [ /_ViewImport, /Views/_ViewImport, /Views/Home/_ViewImport ]
/// </remarks>
public virtual IReadOnlyList<ChunkTreeResult> GetInheritedChunkTreeResults(string pagePath) public virtual IReadOnlyList<ChunkTreeResult> GetInheritedChunkTreeResults(string pagePath)
{ {
if (pagePath == null) if (pagePath == null)
@ -88,7 +94,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
if (chunkTree != null) if (chunkTree != null)
{ {
var result = new ChunkTreeResult(chunkTree, viewImportsPath); var result = new ChunkTreeResult(chunkTree, viewImportsPath);
inheritedChunkTreeResults.Add(result); inheritedChunkTreeResults.Insert(0, result);
} }
} }
@ -102,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
/// <param name="chunkTree">The <see cref="ChunkTree"/> to merge in to.</param> /// <param name="chunkTree">The <see cref="ChunkTree"/> to merge in to.</param>
/// <param name="inheritedChunkTrees"><see cref="IReadOnlyList{ChunkTree}"/> inherited from <c>_ViewImports</c> /// <param name="inheritedChunkTrees"><see cref="IReadOnlyList{ChunkTree}"/> inherited from <c>_ViewImports</c>
/// files.</param> /// files.</param>
/// <param name="defaultModel">The list of chunks to merge.</param> /// <param name="defaultModel">The default model <see cref="Type"/> name.</param>
public void MergeInheritedChunkTrees( public void MergeInheritedChunkTrees(
ChunkTree chunkTree, ChunkTree chunkTree,
IReadOnlyList<ChunkTree> inheritedChunkTrees, IReadOnlyList<ChunkTree> inheritedChunkTrees,
@ -118,44 +124,34 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
throw new ArgumentNullException(nameof(inheritedChunkTrees)); throw new ArgumentNullException(nameof(inheritedChunkTrees));
} }
var mergerMappings = GetMergerMappings(chunkTree, defaultModel); var chunkMergers = GetChunkMergers(chunkTree, defaultModel);
IChunkMerger merger;
// We merge chunks into the ChunkTree in two passes. In the first pass, we traverse the ChunkTree visiting // We merge chunks into the ChunkTree in two passes. In the first pass, we traverse the ChunkTree visiting
// a mapped IChunkMerger for types that are registered. // a mapped IChunkMerger for types that are registered.
foreach (var chunk in chunkTree.Chunks) foreach (var chunk in chunkTree.Chunks)
{ {
if (mergerMappings.TryGetValue(chunk.GetType(), out merger)) foreach (var merger in chunkMergers)
{ {
merger.VisitChunk(chunk); merger.VisitChunk(chunk);
} }
} }
// In the second phase we invoke IChunkMerger.Merge for each chunk that has a mapped merger. var inheritedChunks = _defaultInheritedChunks.Concat(
// During this phase, the merger can either add to the ChunkTree or ignore the chunk based on the merging inheritedChunkTrees.SelectMany(tree => tree.Chunks)).ToArray();
// rules.
// Read the chunks outside in - that is chunks from the _ViewImports closest to the page get merged in first foreach (var merger in chunkMergers)
// and the furthest one last. This allows the merger to ignore a directive like @model that was previously
// seen.
var chunksToMerge = inheritedChunkTrees.SelectMany(tree => tree.Chunks)
.Concat(_defaultInheritedChunks);
foreach (var chunk in chunksToMerge)
{ {
if (mergerMappings.TryGetValue(chunk.GetType(), out merger)) merger.MergeInheritedChunks(chunkTree, inheritedChunks);
{
merger.Merge(chunkTree, chunk);
}
} }
} }
private static Dictionary<Type, IChunkMerger> GetMergerMappings(ChunkTree chunkTree, string defaultModel) private static IChunkMerger[] GetChunkMergers(ChunkTree chunkTree, string defaultModel)
{ {
var modelType = ChunkHelper.GetModelTypeName(chunkTree, defaultModel); var modelType = ChunkHelper.GetModelTypeName(chunkTree, defaultModel);
return new Dictionary<Type, IChunkMerger> return new IChunkMerger[]
{ {
{ typeof(UsingChunk), new UsingChunkMerger() }, new UsingChunkMerger(),
{ typeof(InjectChunk), new InjectChunkMerger(modelType) }, new InjectChunkMerger(modelType),
{ typeof(SetBaseTypeChunk), new SetBaseTypeChunkMerger(modelType) } new SetBaseTypeChunkMerger(modelType)
}; };
} }

View File

@ -1,6 +1,7 @@
// 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNet.Razor.Chunks; using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives namespace Microsoft.AspNet.Mvc.Razor.Directives
@ -20,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
/// Merges an inherited <see cref="Chunk"/> into the <see cref="ChunkTree"/>. /// Merges an inherited <see cref="Chunk"/> into the <see cref="ChunkTree"/>.
/// </summary> /// </summary>
/// <param name="ChunkTree">The <see cref="ChunkTree"/> to merge into.</param> /// <param name="ChunkTree">The <see cref="ChunkTree"/> to merge into.</param>
/// <param name="chunk">The <see cref="Chunk"/> to merge.</param> /// <param name="inheritedChunks">The <see cref="IReadOnlyList{Chunk}"/>s to merge.</param>
void Merge(ChunkTree chunkTree, Chunk chunk); void MergeInheritedChunks(ChunkTree chunkTree, IReadOnlyList<Chunk> inheritedChunks);
} }
} }

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Razor.Chunks; using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives namespace Microsoft.AspNet.Mvc.Razor.Directives
@ -37,29 +38,35 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
throw new ArgumentNullException(nameof(chunk)); throw new ArgumentNullException(nameof(chunk));
} }
var injectChunk = ChunkHelper.EnsureChunk<InjectChunk>(chunk); var injectChunk = chunk as InjectChunk;
injectChunk.TypeName = ChunkHelper.ReplaceTModel(injectChunk.TypeName, _modelType); if (injectChunk != null)
_addedMemberNames.Add(injectChunk.MemberName); {
injectChunk.TypeName = ChunkHelper.ReplaceTModel(injectChunk.TypeName, _modelType);
_addedMemberNames.Add(injectChunk.MemberName);
}
} }
/// <inheritdoc /> /// <inheritdoc />
public void Merge(ChunkTree chunkTree, Chunk chunk) public void MergeInheritedChunks(ChunkTree chunkTree, IReadOnlyList<Chunk> inheritedChunks)
{ {
if (chunkTree == null) if (chunkTree == null)
{ {
throw new ArgumentNullException(nameof(chunkTree)); throw new ArgumentNullException(nameof(chunkTree));
} }
if (chunk == null) if (inheritedChunks == null)
{ {
throw new ArgumentNullException(nameof(chunk)); throw new ArgumentNullException(nameof(inheritedChunks));
} }
var injectChunk = ChunkHelper.EnsureChunk<InjectChunk>(chunk); for (var i = inheritedChunks.Count - 1; i >= 0; i--)
if (!_addedMemberNames.Contains(injectChunk.MemberName))
{ {
_addedMemberNames.Add(injectChunk.MemberName); var injectChunk = inheritedChunks[i] as InjectChunk;
chunkTree.Chunks.Add(TransformChunk(injectChunk)); if (injectChunk != null &&
_addedMemberNames.Add(injectChunk.MemberName))
{
chunkTree.Chunks.Add(TransformChunk(injectChunk));
}
} }
} }

View File

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Razor.Chunks; using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives namespace Microsoft.AspNet.Mvc.Razor.Directives
@ -31,32 +33,38 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
throw new ArgumentNullException(nameof(chunk)); throw new ArgumentNullException(nameof(chunk));
} }
var setBaseTypeChunk = ChunkHelper.EnsureChunk<SetBaseTypeChunk>(chunk); var setBaseTypeChunk = chunk as SetBaseTypeChunk;
setBaseTypeChunk.TypeName = ChunkHelper.ReplaceTModel(setBaseTypeChunk.TypeName, _modelType); if (setBaseTypeChunk != null)
_isBaseTypeSet = true; {
setBaseTypeChunk.TypeName = ChunkHelper.ReplaceTModel(setBaseTypeChunk.TypeName, _modelType);
_isBaseTypeSet = true;
}
} }
/// <inheritdoc /> /// <inheritdoc />
public void Merge(ChunkTree chunkTree, Chunk chunk) public void MergeInheritedChunks(ChunkTree chunkTree, IReadOnlyList<Chunk> inheritedChunks)
{ {
if (chunkTree == null) if (chunkTree == null)
{ {
throw new ArgumentNullException(nameof(chunkTree)); throw new ArgumentNullException(nameof(chunkTree));
} }
if (chunk == null) if (inheritedChunks == null)
{ {
throw new ArgumentNullException(nameof(chunk)); throw new ArgumentNullException(nameof(inheritedChunks));
} }
if (!_isBaseTypeSet) if (!_isBaseTypeSet)
{ {
var baseTypeChunk = ChunkHelper.EnsureChunk<SetBaseTypeChunk>(chunk); for (var i = inheritedChunks.Count - 1; i >= 0; i--)
{
// The base type can set exactly once and the first one we encounter wins. var baseTypeChunk = inheritedChunks[i] as SetBaseTypeChunk;
_isBaseTypeSet = true; if (baseTypeChunk != null)
{
chunkTree.Chunks.Add(TransformChunk(baseTypeChunk)); chunkTree.Chunks.Add(TransformChunk(baseTypeChunk));
break;
}
}
} }
} }

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Razor.Chunks; using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives namespace Microsoft.AspNet.Mvc.Razor.Directives
@ -22,29 +23,33 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
throw new ArgumentNullException(nameof(chunk)); throw new ArgumentNullException(nameof(chunk));
} }
var namespaceChunk = ChunkHelper.EnsureChunk<UsingChunk>(chunk); var namespaceChunk = chunk as UsingChunk;
_currentUsings.Add(namespaceChunk.Namespace); if (namespaceChunk != null)
{
_currentUsings.Add(namespaceChunk.Namespace);
}
} }
/// <inheritdoc /> /// <inheritdoc />
public void Merge(ChunkTree chunkTree, Chunk chunk) public void MergeInheritedChunks(ChunkTree chunkTree, IReadOnlyList<Chunk> inheritedChunks)
{ {
if (chunkTree == null) if (chunkTree == null)
{ {
throw new ArgumentNullException(nameof(chunkTree)); throw new ArgumentNullException(nameof(chunkTree));
} }
if (chunk == null) if (inheritedChunks == null)
{ {
throw new ArgumentNullException(nameof(chunk)); throw new ArgumentNullException(nameof(inheritedChunks));
} }
var namespaceChunk = ChunkHelper.EnsureChunk<UsingChunk>(chunk); var namespaceChunks = inheritedChunks.OfType<UsingChunk>();
foreach (var namespaceChunk in namespaceChunks)
if (!_currentUsings.Contains(namespaceChunk.Namespace))
{ {
_currentUsings.Add(namespaceChunk.Namespace); if (_currentUsings.Add(namespaceChunk.Namespace))
chunkTree.Chunks.Add(namespaceChunk); {
chunkTree.Chunks.Add(namespaceChunk);
}
} }
} }
} }

View File

@ -117,15 +117,8 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
var descriptors = new List<TagHelperDirectiveDescriptor>(); var descriptors = new List<TagHelperDirectiveDescriptor>();
// For tag helpers, the @removeTagHelper only applies tag helpers that were added prior to it. var inheritedChunks = defaultInheritedChunks.Concat(inheritedChunkTrees.SelectMany(tree => tree.Chunks));
// Consequently we must visit tag helpers outside-in - furthest _ViewImports first and nearest one last. foreach (var chunk in inheritedChunks)
// This is different from the behavior of chunk merging where we visit the nearest one first and ignore
// chunks that were previously visited.
var chunksFromViewImports = inheritedChunkTrees
.Reverse()
.SelectMany(tree => tree.Chunks);
var chunksInOrder = defaultInheritedChunks.Concat(chunksFromViewImports);
foreach (var chunk in chunksInOrder)
{ {
// All TagHelperDirectiveDescriptors created here have undefined source locations because the source // All TagHelperDirectiveDescriptors created here have undefined source locations because the source
// that created them is not in the same file. // that created them is not in the same file.

View File

@ -26,22 +26,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Host
return GetString("ArgumentCannotBeNullOrEmpy"); return GetString("ArgumentCannotBeNullOrEmpy");
} }
/// <summary>
/// Argument must be an instance of '{0}'.
/// </summary>
internal static string ArgumentMustBeOfType
{
get { return GetString("ArgumentMustBeOfType"); }
}
/// <summary>
/// Argument must be an instance of '{0}'.
/// </summary>
internal static string FormatArgumentMustBeOfType(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ArgumentMustBeOfType"), p0);
}
/// <summary> /// <summary>
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used. /// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
/// </summary> /// </summary>

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
Version 2.0 Version 2.0
The primary goals of this format is to allow a simple XML format The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes various data types are done through the TypeConverter classes
associated with the data types. associated with the data types.
Example: Example:
... ado.net/XML headers & schema ... ... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader> <resheader name="version">2.0</resheader>
@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment> <comment>This is a comment</comment>
</data> </data>
There are any number of "resheader" rows that contain simple There are any number of "resheader" rows that contain simple
name/value pairs. name/value pairs.
Each data row contains a name, and value. The row also contains a Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture. text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the Classes that don't support this are serialized and stored with the
mimetype set. mimetype set.
The mimetype is used for serialized objects, and tells the The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly: extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below. read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64 mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64 mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64 mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter : using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
--> -->
@ -120,9 +120,6 @@
<data name="ArgumentCannotBeNullOrEmpy" xml:space="preserve"> <data name="ArgumentCannotBeNullOrEmpy" xml:space="preserve">
<value>Value cannot be null or empty.</value> <value>Value cannot be null or empty.</value>
</data> </data>
<data name="ArgumentMustBeOfType" xml:space="preserve">
<value>Argument must be an instance of '{0}'.</value>
</data>
<data name="MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword" xml:space="preserve"> <data name="MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword" xml:space="preserve">
<value>The 'inherits' keyword is not allowed when a '{0}' keyword is used.</value> <value>The 'inherits' keyword is not allowed when a '{0}' keyword is used.</value>
</data> </data>

View File

@ -152,6 +152,19 @@ page:<root>root-content</root>"
Assert.Equal(expected, result.Trim(), ignoreLineEndingDifferences: true); Assert.Equal(expected, result.Trim(), ignoreLineEndingDifferences: true);
} }
[Fact]
public async Task DefaultInheritedTagsCanBeRemoved()
{
// Arrange
var expected =
@"<a href=""~/VirtualPath"">Virtual path</a>";
var result = await Client.GetStringAsync("RemoveDefaultInheritedTagHelpers");
// Assert
Assert.Equal(expected, result.Trim(), ignoreLineEndingDifferences: true);
}
[Fact] [Fact]
public async Task ViewsWithModelMetadataAttributes_CanRenderForm() public async Task ViewsWithModelMetadataAttributes_CanRenderForm()
{ {

View File

@ -40,28 +40,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Assert // Assert
Assert.Collection(chunkTreeResults, Assert.Collection(chunkTreeResults,
chunkTreeResult =>
{
var viewImportsPath = PlatformNormalizer.NormalizePath(@"Views\home\_ViewImports.cshtml");
Assert.Collection(chunkTreeResult.ChunkTree.Chunks,
chunk =>
{
Assert.IsType<LiteralChunk>(chunk);
Assert.Equal(viewImportsPath, chunk.Start.FilePath);
},
chunk =>
{
var usingChunk = Assert.IsType<UsingChunk>(chunk);
Assert.Equal("MyNamespace", usingChunk.Namespace);
Assert.Equal(viewImportsPath, chunk.Start.FilePath);
},
chunk =>
{
Assert.IsType<LiteralChunk>(chunk);
Assert.Equal(viewImportsPath, chunk.Start.FilePath);
});
Assert.Equal(viewImportsPath, chunkTreeResult.FilePath);
},
chunkTreeResult => chunkTreeResult =>
{ {
var viewImportsPath = PlatformNormalizer.NormalizePath(@"Views\_ViewImports.cshtml"); var viewImportsPath = PlatformNormalizer.NormalizePath(@"Views\_ViewImports.cshtml");
@ -88,7 +66,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
var setBaseTypeChunk = Assert.IsType<SetBaseTypeChunk>(chunk); var setBaseTypeChunk = Assert.IsType<SetBaseTypeChunk>(chunk);
Assert.Equal("MyBaseType", setBaseTypeChunk.TypeName); Assert.Equal("MyBaseType", setBaseTypeChunk.TypeName);
Assert.Equal(viewImportsPath, chunk.Start.FilePath); Assert.Equal(viewImportsPath, chunk.Start.FilePath);
}, },
chunk => chunk =>
{ {
@ -106,6 +83,28 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
Assert.Equal(viewImportsPath, chunk.Start.FilePath); Assert.Equal(viewImportsPath, chunk.Start.FilePath);
}); });
Assert.Equal(viewImportsPath, chunkTreeResult.FilePath); Assert.Equal(viewImportsPath, chunkTreeResult.FilePath);
},
chunkTreeResult =>
{
var viewImportsPath = PlatformNormalizer.NormalizePath(@"Views\home\_ViewImports.cshtml");
Assert.Collection(chunkTreeResult.ChunkTree.Chunks,
chunk =>
{
Assert.IsType<LiteralChunk>(chunk);
Assert.Equal(viewImportsPath, chunk.Start.FilePath);
},
chunk =>
{
var usingChunk = Assert.IsType<UsingChunk>(chunk);
Assert.Equal("MyNamespace", usingChunk.Namespace);
Assert.Equal(viewImportsPath, chunk.Start.FilePath);
},
chunk =>
{
Assert.IsType<LiteralChunk>(chunk);
Assert.Equal(viewImportsPath, chunk.Start.FilePath);
});
Assert.Equal(viewImportsPath, chunkTreeResult.FilePath);
}); });
} }
@ -173,10 +172,10 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
utility.MergeInheritedChunkTrees(chunkTree, inheritedChunkTrees, "dynamic"); utility.MergeInheritedChunkTrees(chunkTree, inheritedChunkTrees, "dynamic");
// Assert // Assert
Assert.Equal(3, chunkTree.Chunks.Count); Assert.Collection(chunkTree.Chunks,
Assert.Same(inheritedChunkTrees[0].Chunks[0], chunkTree.Chunks[0]); chunk => Assert.Same(defaultChunks[1], chunk),
Assert.Same(inheritedChunkTrees[1].Chunks[0], chunkTree.Chunks[1]); chunk => Assert.Same(inheritedChunkTrees[0].Chunks[0], chunk),
Assert.Same(defaultChunks[0], chunkTree.Chunks[2]); chunk => Assert.Same(defaultChunks[0], chunk));
} }
} }
} }

View File

@ -2,24 +2,12 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.Chunks; using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Testing;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.Razor.Directives namespace Microsoft.AspNet.Mvc.Razor.Directives
{ {
public class InjectChunkMergerTest public class InjectChunkMergerTest
{ {
[Fact]
public void Visit_ThrowsIfThePassedInChunkIsNotAInjectChunk()
{
// Arrange
var expected = "Argument must be an instance of 'Microsoft.AspNet.Mvc.Razor.InjectChunk'.";
var merger = new InjectChunkMerger("dynamic");
// Act and Assert
ExceptionAssert.ThrowsArgument(() => merger.VisitChunk(new LiteralChunk()), "chunk", expected);
}
[Theory] [Theory]
[InlineData("MyApp.TestHelper<TModel>", "MyApp.TestHelper<Person>")] [InlineData("MyApp.TestHelper<TModel>", "MyApp.TestHelper<Person>")]
[InlineData("TestBaseType", "TestBaseType")] [InlineData("TestBaseType", "TestBaseType")]
@ -37,17 +25,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
Assert.Equal("TestHelper", chunk.MemberName); Assert.Equal("TestHelper", chunk.MemberName);
} }
[Fact]
public void Merge_ThrowsIfThePassedInChunkIsNotAInjectChunk()
{
// Arrange
var expected = "Argument must be an instance of 'Microsoft.AspNet.Mvc.Razor.InjectChunk'.";
var merger = new InjectChunkMerger("dynamic");
// Act and Assert
ExceptionAssert.ThrowsArgument(() => merger.Merge(new ChunkTree(), new LiteralChunk()), "chunk", expected);
}
[Fact] [Fact]
public void Merge_AddsChunkIfChunkWithMatchingPropertyNameWasNotVisitedInChunkTree() public void Merge_AddsChunkIfChunkWithMatchingPropertyNameWasNotVisitedInChunkTree()
{ {
@ -56,9 +33,13 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
var expectedProperty = "MyHelper"; var expectedProperty = "MyHelper";
var merger = new InjectChunkMerger("dynamic"); var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk(expectedType, expectedProperty)
};
// Act // Act
merger.Merge(chunkTree, new InjectChunk(expectedType, expectedProperty)); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert // Assert
var chunk = Assert.Single(chunkTree.Chunks); var chunk = Assert.Single(chunkTree.Chunks);
@ -73,10 +54,14 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange // Arrange
var merger = new InjectChunkMerger("dynamic"); var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk("MyTypeB", "MyProperty")
};
// Act // Act
merger.VisitChunk(new InjectChunk("MyTypeA", "MyProperty")); merger.VisitChunk(new InjectChunk("MyTypeA", "MyProperty"));
merger.Merge(chunkTree, new InjectChunk("MyTypeB", "MyProperty")); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert // Assert
Assert.Empty(chunkTree.Chunks); Assert.Empty(chunkTree.Chunks);
@ -88,11 +73,15 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange // Arrange
var merger = new InjectChunkMerger("dynamic"); var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk("MyTypeB", "different-property"),
new InjectChunk("MyType", "myproperty"),
};
// Act // Act
merger.VisitChunk(new InjectChunk("MyType", "MyProperty")); merger.VisitChunk(new InjectChunk("MyType", "MyProperty"));
merger.Merge(chunkTree, new InjectChunk("MyType", "myproperty")); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
merger.Merge(chunkTree, new InjectChunk("MyTypeB", "different-property"));
// Assert // Assert
Assert.Equal(2, chunkTree.Chunks.Count); Assert.Equal(2, chunkTree.Chunks.Count);
@ -111,9 +100,13 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange // Arrange
var merger = new InjectChunkMerger("dynamic"); var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk("MyHelper<TModel>", "MyProperty")
};
// Act // Act
merger.Merge(chunkTree, new InjectChunk("MyHelper<TModel>", "MyProperty")); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert // Assert
var chunk = Assert.Single(chunkTree.Chunks); var chunk = Assert.Single(chunkTree.Chunks);
@ -128,9 +121,13 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange // Arrange
var merger = new InjectChunkMerger("MyTestModel2"); var merger = new InjectChunkMerger("MyTestModel2");
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk("MyHelper<TModel>", "MyProperty")
};
// Act // Act
merger.Merge(chunkTree, new InjectChunk("MyHelper<TModel>", "MyProperty")); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert // Assert
var chunk = Assert.Single(chunkTree.Chunks); var chunk = Assert.Single(chunkTree.Chunks);
@ -140,21 +137,36 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
} }
[Fact] [Fact]
public void Merge_IgnoresChunkIfChunkWithMatchingPropertyNameWasPreviouslyMerged() public void Merge_UsesTheLastInjectChunkOfAPropertyName()
{ {
// Arrange // Arrange
var merger = new InjectChunkMerger("dynamic"); var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new Chunk[]
{
new LiteralChunk(),
new InjectChunk("SomeOtherType", "Property"),
new InjectChunk("DifferentPropertyType", "DifferentProperty"),
new InjectChunk("SomeType", "Property"),
};
// Act // Act
merger.Merge(chunkTree, new InjectChunk("SomeType", "Property")); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
merger.Merge(chunkTree, new InjectChunk("SomeOtherType", "Property"));
// Assert // Assert
var chunk = Assert.Single(chunkTree.Chunks); Assert.Collection(chunkTree.Chunks,
var injectChunk = Assert.IsType<InjectChunk>(chunk); chunk =>
Assert.Equal("SomeType", injectChunk.TypeName); {
Assert.Equal("Property", injectChunk.MemberName); var injectChunk = Assert.IsType<InjectChunk>(chunk);
Assert.Equal("SomeType", injectChunk.TypeName);
Assert.Equal("Property", injectChunk.MemberName);
},
chunk =>
{
var injectChunk = Assert.IsType<InjectChunk>(chunk);
Assert.Equal("DifferentPropertyType", injectChunk.TypeName);
Assert.Equal("DifferentProperty", injectChunk.MemberName);
});
} }
} }
} }

View File

@ -2,25 +2,12 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.Chunks; using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Testing;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.Razor.Directives namespace Microsoft.AspNet.Mvc.Razor.Directives
{ {
public class SetBaseTypeChunkMergerTest public class SetBaseTypeChunkMergerTest
{ {
[Fact]
public void Visit_ThrowsIfThePassedInChunkIsNotASetBaseTypeChunk()
{
// Arrange
var expected = "Argument must be an instance of " +
"'Microsoft.AspNet.Razor.Chunks.SetBaseTypeChunk'.";
var merger = new SetBaseTypeChunkMerger("dynamic");
// Act and Assert
ExceptionAssert.ThrowsArgument(() => merger.VisitChunk(new LiteralChunk()), "chunk", expected);
}
[Theory] [Theory]
[InlineData("MyApp.BaseType<TModel>", "MyApp.BaseType<Person>")] [InlineData("MyApp.BaseType<TModel>", "MyApp.BaseType<Person>")]
[InlineData("TestBaseType", "TestBaseType")] [InlineData("TestBaseType", "TestBaseType")]
@ -40,18 +27,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
Assert.Equal(expectedValue, chunk.TypeName); Assert.Equal(expectedValue, chunk.TypeName);
} }
[Fact]
public void Merge_ThrowsIfThePassedInChunkIsNotASetBaseTypeChunk()
{
// Arrange
var expected = "Argument must be an instance of " +
"'Microsoft.AspNet.Razor.Chunks.SetBaseTypeChunk'.";
var merger = new SetBaseTypeChunkMerger("dynamic");
// Act and Assert
ExceptionAssert.ThrowsArgument(() => merger.Merge(new ChunkTree(), new LiteralChunk()), "chunk", expected);
}
[Fact] [Fact]
public void Merge_SetsBaseTypeIfItHasNotBeenSetInChunkTree() public void Merge_SetsBaseTypeIfItHasNotBeenSetInChunkTree()
{ {
@ -59,9 +34,13 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
var expected = "MyApp.Razor.MyBaseType"; var expected = "MyApp.Razor.MyBaseType";
var merger = new SetBaseTypeChunkMerger("dynamic"); var merger = new SetBaseTypeChunkMerger("dynamic");
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new SetBaseTypeChunk { TypeName = expected }
};
// Act // Act
merger.Merge(chunkTree, new SetBaseTypeChunk { TypeName = expected }); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert // Assert
var chunk = Assert.Single(chunkTree.Chunks); var chunk = Assert.Single(chunkTree.Chunks);
@ -75,25 +54,34 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange // Arrange
var merger = new SetBaseTypeChunkMerger("dynamic"); var merger = new SetBaseTypeChunkMerger("dynamic");
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new SetBaseTypeChunk { TypeName = "MyBaseType2" }
};
// Act // Act
merger.VisitChunk(new SetBaseTypeChunk { TypeName = "MyBaseType1" }); merger.VisitChunk(new SetBaseTypeChunk { TypeName = "MyBaseType1" });
merger.Merge(chunkTree, new SetBaseTypeChunk { TypeName = "MyBaseType2" }); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert // Assert
Assert.Empty(chunkTree.Chunks); Assert.Empty(chunkTree.Chunks);
} }
[Fact] [Fact]
public void Merge_IgnoresSetBaseTypeChunksIfSetBaseTypeWasPreviouslyMerged() public void Merge_PicksLastBaseTypeChunkFromChunkTree()
{ {
// Arrange // Arrange
var merger = new SetBaseTypeChunkMerger("dynamic"); var merger = new SetBaseTypeChunkMerger("dynamic");
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new Chunk[]
{
new SetBaseTypeChunk { TypeName = "MyBase2" },
new LiteralChunk(),
new SetBaseTypeChunk { TypeName = "MyBase1" },
};
// Act // Act
merger.Merge(chunkTree, new SetBaseTypeChunk { TypeName = "MyBase1" }); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
merger.Merge(chunkTree, new SetBaseTypeChunk { TypeName = "MyBase2" });
// Assert // Assert
var chunk = Assert.Single(chunkTree.Chunks); var chunk = Assert.Single(chunkTree.Chunks);

View File

@ -9,28 +9,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
{ {
public class UsingChunkMergerTest public class UsingChunkMergerTest
{ {
[Fact]
public void Visit_ThrowsIfThePassedInChunkIsNotAUsingChunk()
{
// Arrange
var expected = "Argument must be an instance of 'Microsoft.AspNet.Razor.Chunks.UsingChunk'.";
var merger = new UsingChunkMerger();
// Act and Assert
ExceptionAssert.ThrowsArgument(() => merger.VisitChunk(new LiteralChunk()), "chunk", expected);
}
[Fact]
public void Merge_ThrowsIfThePassedInChunkIsNotAUsingChunk()
{
// Arrange
var expected = "Argument must be an instance of 'Microsoft.AspNet.Razor.Chunks.UsingChunk'.";
var merger = new UsingChunkMerger();
// Act and Assert
ExceptionAssert.ThrowsArgument(() => merger.Merge(new ChunkTree(), new LiteralChunk()), "chunk", expected);
}
[Fact] [Fact]
public void Merge_AddsNamespacesThatHaveNotBeenVisitedInChunkTree() public void Merge_AddsNamespacesThatHaveNotBeenVisitedInChunkTree()
{ {
@ -38,10 +16,14 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
var expected = "MyApp.Models"; var expected = "MyApp.Models";
var merger = new UsingChunkMerger(); var merger = new UsingChunkMerger();
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new Chunk[]
{
new UsingChunk { Namespace = expected },
};
// Act // Act
merger.VisitChunk(new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" }); merger.VisitChunk(new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" });
merger.Merge(chunkTree, new UsingChunk { Namespace = expected }); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert // Assert
var chunk = Assert.Single(chunkTree.Chunks); var chunk = Assert.Single(chunkTree.Chunks);
@ -55,26 +37,36 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange // Arrange
var merger = new UsingChunkMerger(); var merger = new UsingChunkMerger();
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new Chunk[]
{
new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" },
new InjectChunk("Foo", "Bar")
};
// Act // Act
merger.VisitChunk(new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" }); merger.VisitChunk(new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" });
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" }); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert // Assert
Assert.Empty(chunkTree.Chunks); Assert.Empty(chunkTree.Chunks);
} }
[Fact] [Fact]
public void Merge_IgnoresNamespacesThatHaveBeenVisitedDuringMerge() public void Merge_DoesNotAddMoreThanOneInstanceOfTheSameInheritedNamespace()
{ {
// Arrange // Arrange
var merger = new UsingChunkMerger(); var merger = new UsingChunkMerger();
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new Chunk[]
{
new LiteralChunk(),
new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" },
new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" },
new UsingChunk { Namespace = "Microsoft.AspNet.Mvc.Razor" }
};
// Act // Act
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" }); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" });
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc.Razor" });
// Assert // Assert
Assert.Equal(2, chunkTree.Chunks.Count); Assert.Equal(2, chunkTree.Chunks.Count);
@ -85,15 +77,19 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
} }
[Fact] [Fact]
public void Merge_MacthesNamespacesInCaseSensitiveManner() public void Merge_MatchesNamespacesInCaseSensitiveManner()
{ {
// Arrange // Arrange
var merger = new UsingChunkMerger(); var merger = new UsingChunkMerger();
var chunkTree = new ChunkTree(); var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" },
new UsingChunk { Namespace = "Microsoft.AspNet.mvc" }
};
// Act // Act
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" }); merger.MergeInheritedChunks(chunkTree, inheritedChunks);
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.mvc" });
// Assert // Assert
Assert.Equal(2, chunkTree.Chunks.Count); Assert.Equal(2, chunkTree.Chunks.Count);

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.Razor; using Microsoft.AspNet.Razor;
using Microsoft.AspNet.Razor.Chunks; using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Razor.Parser; using Microsoft.AspNet.Razor.Parser;
@ -66,8 +65,8 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
new[] new[]
{ {
CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP1" }),
CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP2" }), CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP2" }),
CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP1" }),
}, },
new[] { CreateDirectiveDescriptor("THP1", TagHelperDirectiveType.TagHelperPrefix) } new[] { CreateDirectiveDescriptor("THP1", TagHelperDirectiveType.TagHelperPrefix) }
}, },
@ -89,10 +88,10 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
new[] new[]
{ {
CreateChunkTree(new RemoveTagHelperChunk { LookupText = "RTH" }),
CreateChunkTree( CreateChunkTree(
new LiteralChunk { Text = "Hello world" }, new LiteralChunk { Text = "Hello world" },
new AddTagHelperChunk { LookupText = "ATH" }), new AddTagHelperChunk { LookupText = "ATH" }),
CreateChunkTree(new RemoveTagHelperChunk { LookupText = "RTH" })
}, },
new[] new[]
{ {
@ -103,11 +102,11 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
new[] new[]
{ {
CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP" }), CreateChunkTree(new RemoveTagHelperChunk { LookupText = "RTH" }),
CreateChunkTree( CreateChunkTree(
new LiteralChunk { Text = "Hello world" }, new LiteralChunk { Text = "Hello world" },
new AddTagHelperChunk { LookupText = "ATH" }), new AddTagHelperChunk { LookupText = "ATH" }),
CreateChunkTree(new RemoveTagHelperChunk { LookupText = "RTH" }) CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP" }),
}, },
new[] new[]
{ {
@ -119,10 +118,10 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
new[] new[]
{ {
CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP1" }),
CreateChunkTree(new AddTagHelperChunk { LookupText = "ATH" }),
CreateChunkTree(new RemoveTagHelperChunk { LookupText = "RTH" }),
CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP2" }), CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP2" }),
CreateChunkTree(new RemoveTagHelperChunk { LookupText = "RTH" }),
CreateChunkTree(new AddTagHelperChunk { LookupText = "ATH" }),
CreateChunkTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP1" }),
}, },
new[] new[]
{ {

View File

@ -16,13 +16,13 @@ namespace Asp
} }
#line hidden #line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
#line hidden #line hidden

View File

@ -30,13 +30,13 @@ using MyNamespace
#line hidden #line hidden
{ get; private set; } { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
#line hidden #line hidden

View File

@ -38,11 +38,11 @@ namespace Asp
#line hidden #line hidden
{ get; private set; } { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
#line hidden #line hidden

View File

@ -54,11 +54,11 @@ namespace Asp
#line hidden #line hidden
{ get; private set; } { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
#line hidden #line hidden

View File

@ -22,13 +22,13 @@ namespace Asp
} }
#line hidden #line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; }
#line hidden #line hidden

View File

@ -38,13 +38,13 @@ namespace Asp
} }
#line hidden #line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; }
#line hidden #line hidden

View File

@ -16,13 +16,13 @@ namespace Asp
} }
#line hidden #line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
#line hidden #line hidden

View File

@ -24,13 +24,13 @@ using MyNamespace
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public MyApp MyPropertyName { get; private set; } public MyApp MyPropertyName { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
#line hidden #line hidden

View File

@ -26,11 +26,11 @@ namespace Asp
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public MyService<MyModel> Html { get; private set; } public MyService<MyModel> Html { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
#line hidden #line hidden

View File

@ -30,11 +30,11 @@ namespace Asp
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public MyService<MyModel> Html2 { get; private set; } public MyService<MyModel> Html2 { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
#line hidden #line hidden

View File

@ -22,13 +22,13 @@ namespace Asp
} }
#line hidden #line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; }
#line hidden #line hidden

View File

@ -31,13 +31,13 @@ namespace Asp
} }
#line hidden #line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; } public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute] [Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; }
#line hidden #line hidden

View File

@ -0,0 +1,12 @@
// 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.AspNet.Mvc;
namespace TagHelpersWebSite.Controllers
{
public class RemoveDefaultInheritedTagHelpersController : Controller
{
public IActionResult Index() => View();
}
}

View File

@ -0,0 +1,4 @@
@{
Layout = null;
}
<a href="~/VirtualPath">Virtual path</a>

View File

@ -0,0 +1 @@
@removeTagHelper "*, Microsoft.AspNet.Mvc.Razor"