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.Linq;
using Microsoft.AspNet.Mvc.Razor.Host;
using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives
@ -15,33 +14,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
{
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>
/// Returns the <see cref="ModelChunk"/> used to determine the model name for the page generated
/// 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>
/// <returns>A <see cref="IReadOnlyList{ChunkTreeResult}"/> of parsed <c>_ViewImports</c>
/// <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)
{
if (pagePath == null)
@ -88,7 +94,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
if (chunkTree != null)
{
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="inheritedChunkTrees"><see cref="IReadOnlyList{ChunkTree}"/> inherited from <c>_ViewImports</c>
/// 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(
ChunkTree chunkTree,
IReadOnlyList<ChunkTree> inheritedChunkTrees,
@ -118,44 +124,34 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
throw new ArgumentNullException(nameof(inheritedChunkTrees));
}
var mergerMappings = GetMergerMappings(chunkTree, defaultModel);
IChunkMerger merger;
var chunkMergers = GetChunkMergers(chunkTree, defaultModel);
// 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.
foreach (var chunk in chunkTree.Chunks)
{
if (mergerMappings.TryGetValue(chunk.GetType(), out merger))
foreach (var merger in chunkMergers)
{
merger.VisitChunk(chunk);
}
}
// In the second phase we invoke IChunkMerger.Merge for each chunk that has a mapped merger.
// During this phase, the merger can either add to the ChunkTree or ignore the chunk based on the merging
// rules.
// Read the chunks outside in - that is chunks from the _ViewImports closest to the page get merged in first
// 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)
var inheritedChunks = _defaultInheritedChunks.Concat(
inheritedChunkTrees.SelectMany(tree => tree.Chunks)).ToArray();
foreach (var merger in chunkMergers)
{
if (mergerMappings.TryGetValue(chunk.GetType(), out merger))
{
merger.Merge(chunkTree, chunk);
}
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
}
}
private static Dictionary<Type, IChunkMerger> GetMergerMappings(ChunkTree chunkTree, string defaultModel)
private static IChunkMerger[] GetChunkMergers(ChunkTree chunkTree, string defaultModel)
{
var modelType = ChunkHelper.GetModelTypeName(chunkTree, defaultModel);
return new Dictionary<Type, IChunkMerger>
return new IChunkMerger[]
{
{ typeof(UsingChunk), new UsingChunkMerger() },
{ typeof(InjectChunk), new InjectChunkMerger(modelType) },
{ typeof(SetBaseTypeChunk), new SetBaseTypeChunkMerger(modelType) }
new UsingChunkMerger(),
new InjectChunkMerger(modelType),
new SetBaseTypeChunkMerger(modelType)
};
}

View File

@ -1,6 +1,7 @@
// 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.Collections.Generic;
using Microsoft.AspNet.Razor.Chunks;
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"/>.
/// </summary>
/// <param name="ChunkTree">The <see cref="ChunkTree"/> to merge into.</param>
/// <param name="chunk">The <see cref="Chunk"/> to merge.</param>
void Merge(ChunkTree chunkTree, Chunk chunk);
/// <param name="inheritedChunks">The <see cref="IReadOnlyList{Chunk}"/>s to merge.</param>
void MergeInheritedChunks(ChunkTree chunkTree, IReadOnlyList<Chunk> inheritedChunks);
}
}

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives
@ -37,29 +38,35 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
throw new ArgumentNullException(nameof(chunk));
}
var injectChunk = ChunkHelper.EnsureChunk<InjectChunk>(chunk);
injectChunk.TypeName = ChunkHelper.ReplaceTModel(injectChunk.TypeName, _modelType);
_addedMemberNames.Add(injectChunk.MemberName);
var injectChunk = chunk as InjectChunk;
if (injectChunk != null)
{
injectChunk.TypeName = ChunkHelper.ReplaceTModel(injectChunk.TypeName, _modelType);
_addedMemberNames.Add(injectChunk.MemberName);
}
}
/// <inheritdoc />
public void Merge(ChunkTree chunkTree, Chunk chunk)
public void MergeInheritedChunks(ChunkTree chunkTree, IReadOnlyList<Chunk> inheritedChunks)
{
if (chunkTree == null)
{
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);
if (!_addedMemberNames.Contains(injectChunk.MemberName))
for (var i = inheritedChunks.Count - 1; i >= 0; i--)
{
_addedMemberNames.Add(injectChunk.MemberName);
chunkTree.Chunks.Add(TransformChunk(injectChunk));
var injectChunk = inheritedChunks[i] as 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.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Mvc.Razor.Directives
@ -31,32 +33,38 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
throw new ArgumentNullException(nameof(chunk));
}
var setBaseTypeChunk = ChunkHelper.EnsureChunk<SetBaseTypeChunk>(chunk);
setBaseTypeChunk.TypeName = ChunkHelper.ReplaceTModel(setBaseTypeChunk.TypeName, _modelType);
_isBaseTypeSet = true;
var setBaseTypeChunk = chunk as SetBaseTypeChunk;
if (setBaseTypeChunk != null)
{
setBaseTypeChunk.TypeName = ChunkHelper.ReplaceTModel(setBaseTypeChunk.TypeName, _modelType);
_isBaseTypeSet = true;
}
}
/// <inheritdoc />
public void Merge(ChunkTree chunkTree, Chunk chunk)
public void MergeInheritedChunks(ChunkTree chunkTree, IReadOnlyList<Chunk> inheritedChunks)
{
if (chunkTree == null)
{
throw new ArgumentNullException(nameof(chunkTree));
}
if (chunk == null)
if (inheritedChunks == null)
{
throw new ArgumentNullException(nameof(chunk));
throw new ArgumentNullException(nameof(inheritedChunks));
}
if (!_isBaseTypeSet)
{
var baseTypeChunk = ChunkHelper.EnsureChunk<SetBaseTypeChunk>(chunk);
// The base type can set exactly once and the first one we encounter wins.
_isBaseTypeSet = true;
chunkTree.Chunks.Add(TransformChunk(baseTypeChunk));
for (var i = inheritedChunks.Count - 1; i >= 0; i--)
{
var baseTypeChunk = inheritedChunks[i] as SetBaseTypeChunk;
if (baseTypeChunk != null)
{
chunkTree.Chunks.Add(TransformChunk(baseTypeChunk));
break;
}
}
}
}

View File

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

View File

@ -117,15 +117,8 @@ namespace Microsoft.AspNet.Mvc.Razor
{
var descriptors = new List<TagHelperDirectiveDescriptor>();
// For tag helpers, the @removeTagHelper only applies tag helpers that were added prior to it.
// Consequently we must visit tag helpers outside-in - furthest _ViewImports first and nearest one last.
// 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)
var inheritedChunks = defaultInheritedChunks.Concat(inheritedChunkTrees.SelectMany(tree => tree.Chunks));
foreach (var chunk in inheritedChunks)
{
// All TagHelperDirectiveDescriptors created here have undefined source locations because the source
// that created them is not in the same file.

View File

@ -26,22 +26,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Host
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>
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
/// </summary>

View File

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

View File

@ -152,6 +152,19 @@ page:<root>root-content</root>"
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]
public async Task ViewsWithModelMetadataAttributes_CanRenderForm()
{

View File

@ -40,28 +40,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Assert
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 =>
{
var viewImportsPath = PlatformNormalizer.NormalizePath(@"Views\_ViewImports.cshtml");
@ -88,7 +66,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
var setBaseTypeChunk = Assert.IsType<SetBaseTypeChunk>(chunk);
Assert.Equal("MyBaseType", setBaseTypeChunk.TypeName);
Assert.Equal(viewImportsPath, chunk.Start.FilePath);
},
chunk =>
{
@ -106,6 +83,28 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
Assert.Equal(viewImportsPath, chunk.Start.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");
// Assert
Assert.Equal(3, chunkTree.Chunks.Count);
Assert.Same(inheritedChunkTrees[0].Chunks[0], chunkTree.Chunks[0]);
Assert.Same(inheritedChunkTrees[1].Chunks[0], chunkTree.Chunks[1]);
Assert.Same(defaultChunks[0], chunkTree.Chunks[2]);
Assert.Collection(chunkTree.Chunks,
chunk => Assert.Same(defaultChunks[1], chunk),
chunk => Assert.Same(inheritedChunkTrees[0].Chunks[0], chunk),
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.
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Testing;
using Xunit;
namespace Microsoft.AspNet.Mvc.Razor.Directives
{
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]
[InlineData("MyApp.TestHelper<TModel>", "MyApp.TestHelper<Person>")]
[InlineData("TestBaseType", "TestBaseType")]
@ -37,17 +25,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
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]
public void Merge_AddsChunkIfChunkWithMatchingPropertyNameWasNotVisitedInChunkTree()
{
@ -56,9 +33,13 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
var expectedProperty = "MyHelper";
var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk(expectedType, expectedProperty)
};
// Act
merger.Merge(chunkTree, new InjectChunk(expectedType, expectedProperty));
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
var chunk = Assert.Single(chunkTree.Chunks);
@ -73,10 +54,14 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange
var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk("MyTypeB", "MyProperty")
};
// Act
merger.VisitChunk(new InjectChunk("MyTypeA", "MyProperty"));
merger.Merge(chunkTree, new InjectChunk("MyTypeB", "MyProperty"));
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
Assert.Empty(chunkTree.Chunks);
@ -88,11 +73,15 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange
var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk("MyTypeB", "different-property"),
new InjectChunk("MyType", "myproperty"),
};
// Act
merger.VisitChunk(new InjectChunk("MyType", "MyProperty"));
merger.Merge(chunkTree, new InjectChunk("MyType", "myproperty"));
merger.Merge(chunkTree, new InjectChunk("MyTypeB", "different-property"));
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
Assert.Equal(2, chunkTree.Chunks.Count);
@ -111,9 +100,13 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange
var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk("MyHelper<TModel>", "MyProperty")
};
// Act
merger.Merge(chunkTree, new InjectChunk("MyHelper<TModel>", "MyProperty"));
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
var chunk = Assert.Single(chunkTree.Chunks);
@ -128,9 +121,13 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange
var merger = new InjectChunkMerger("MyTestModel2");
var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new InjectChunk("MyHelper<TModel>", "MyProperty")
};
// Act
merger.Merge(chunkTree, new InjectChunk("MyHelper<TModel>", "MyProperty"));
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
var chunk = Assert.Single(chunkTree.Chunks);
@ -140,21 +137,36 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
}
[Fact]
public void Merge_IgnoresChunkIfChunkWithMatchingPropertyNameWasPreviouslyMerged()
public void Merge_UsesTheLastInjectChunkOfAPropertyName()
{
// Arrange
var merger = new InjectChunkMerger("dynamic");
var chunkTree = new ChunkTree();
var inheritedChunks = new Chunk[]
{
new LiteralChunk(),
new InjectChunk("SomeOtherType", "Property"),
new InjectChunk("DifferentPropertyType", "DifferentProperty"),
new InjectChunk("SomeType", "Property"),
};
// Act
merger.Merge(chunkTree, new InjectChunk("SomeType", "Property"));
merger.Merge(chunkTree, new InjectChunk("SomeOtherType", "Property"));
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
var chunk = Assert.Single(chunkTree.Chunks);
var injectChunk = Assert.IsType<InjectChunk>(chunk);
Assert.Equal("SomeType", injectChunk.TypeName);
Assert.Equal("Property", injectChunk.MemberName);
Assert.Collection(chunkTree.Chunks,
chunk =>
{
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.
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Testing;
using Xunit;
namespace Microsoft.AspNet.Mvc.Razor.Directives
{
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]
[InlineData("MyApp.BaseType<TModel>", "MyApp.BaseType<Person>")]
[InlineData("TestBaseType", "TestBaseType")]
@ -40,18 +27,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
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]
public void Merge_SetsBaseTypeIfItHasNotBeenSetInChunkTree()
{
@ -59,9 +34,13 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
var expected = "MyApp.Razor.MyBaseType";
var merger = new SetBaseTypeChunkMerger("dynamic");
var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new SetBaseTypeChunk { TypeName = expected }
};
// Act
merger.Merge(chunkTree, new SetBaseTypeChunk { TypeName = expected });
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
var chunk = Assert.Single(chunkTree.Chunks);
@ -75,25 +54,34 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange
var merger = new SetBaseTypeChunkMerger("dynamic");
var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new SetBaseTypeChunk { TypeName = "MyBaseType2" }
};
// Act
merger.VisitChunk(new SetBaseTypeChunk { TypeName = "MyBaseType1" });
merger.Merge(chunkTree, new SetBaseTypeChunk { TypeName = "MyBaseType2" });
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
Assert.Empty(chunkTree.Chunks);
}
[Fact]
public void Merge_IgnoresSetBaseTypeChunksIfSetBaseTypeWasPreviouslyMerged()
public void Merge_PicksLastBaseTypeChunkFromChunkTree()
{
// Arrange
var merger = new SetBaseTypeChunkMerger("dynamic");
var chunkTree = new ChunkTree();
var inheritedChunks = new Chunk[]
{
new SetBaseTypeChunk { TypeName = "MyBase2" },
new LiteralChunk(),
new SetBaseTypeChunk { TypeName = "MyBase1" },
};
// Act
merger.Merge(chunkTree, new SetBaseTypeChunk { TypeName = "MyBase1" });
merger.Merge(chunkTree, new SetBaseTypeChunk { TypeName = "MyBase2" });
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
var chunk = Assert.Single(chunkTree.Chunks);

View File

@ -9,28 +9,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
{
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]
public void Merge_AddsNamespacesThatHaveNotBeenVisitedInChunkTree()
{
@ -38,10 +16,14 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
var expected = "MyApp.Models";
var merger = new UsingChunkMerger();
var chunkTree = new ChunkTree();
var inheritedChunks = new Chunk[]
{
new UsingChunk { Namespace = expected },
};
// Act
merger.VisitChunk(new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" });
merger.Merge(chunkTree, new UsingChunk { Namespace = expected });
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
var chunk = Assert.Single(chunkTree.Chunks);
@ -55,26 +37,36 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
// Arrange
var merger = new UsingChunkMerger();
var chunkTree = new ChunkTree();
var inheritedChunks = new Chunk[]
{
new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" },
new InjectChunk("Foo", "Bar")
};
// Act
merger.VisitChunk(new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" });
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" });
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
Assert.Empty(chunkTree.Chunks);
}
[Fact]
public void Merge_IgnoresNamespacesThatHaveBeenVisitedDuringMerge()
public void Merge_DoesNotAddMoreThanOneInstanceOfTheSameInheritedNamespace()
{
// Arrange
var merger = new UsingChunkMerger();
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
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" });
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" });
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc.Razor" });
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
Assert.Equal(2, chunkTree.Chunks.Count);
@ -85,15 +77,19 @@ namespace Microsoft.AspNet.Mvc.Razor.Directives
}
[Fact]
public void Merge_MacthesNamespacesInCaseSensitiveManner()
public void Merge_MatchesNamespacesInCaseSensitiveManner()
{
// Arrange
var merger = new UsingChunkMerger();
var chunkTree = new ChunkTree();
var inheritedChunks = new[]
{
new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" },
new UsingChunk { Namespace = "Microsoft.AspNet.mvc" }
};
// Act
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.Mvc" });
merger.Merge(chunkTree, new UsingChunk { Namespace = "Microsoft.AspNet.mvc" });
merger.MergeInheritedChunks(chunkTree, inheritedChunks);
// Assert
Assert.Equal(2, chunkTree.Chunks.Count);

View File

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

View File

@ -16,13 +16,13 @@ namespace Asp
}
#line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

View File

@ -30,13 +30,13 @@ using MyNamespace
#line hidden
{ get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

View File

@ -38,11 +38,11 @@ namespace Asp
#line hidden
{ get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

View File

@ -54,11 +54,11 @@ namespace Asp
#line hidden
{ get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

View File

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

View File

@ -38,13 +38,13 @@ namespace Asp
}
#line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

View File

@ -16,13 +16,13 @@ namespace Asp
}
#line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

View File

@ -24,13 +24,13 @@ using MyNamespace
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public MyApp MyPropertyName { get; private set; }
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

View File

@ -26,11 +26,11 @@ namespace Asp
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public MyService<MyModel> Html { get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

View File

@ -30,11 +30,11 @@ namespace Asp
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public MyService<MyModel> Html2 { get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

View File

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

View File

@ -31,13 +31,13 @@ namespace Asp
}
#line hidden
[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; }
[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]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[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

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"