diff --git a/src/Microsoft.AspNet.Razor.Runtime/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Razor.Runtime/Properties/Resources.Designer.cs
index 5a0fccdfdb..e9d4cc8127 100644
--- a/src/Microsoft.AspNet.Razor.Runtime/Properties/Resources.Designer.cs
+++ b/src/Microsoft.AspNet.Razor.Runtime/Properties/Resources.Designer.cs
@@ -62,6 +62,22 @@ namespace Microsoft.AspNet.Razor.Runtime
return GetString("TagHelperTypeResolver_TagHelperAssemblyNameCannotBeEmptyOrNull");
}
+ ///
+ /// Must call '{2}.{1}' before calling '{2}.{0}'.
+ ///
+ internal static string ScopeManager_EndCannotBeCalledWithoutACallToBegin
+ {
+ get { return GetString("ScopeManager_EndCannotBeCalledWithoutACallToBegin"); }
+ }
+
+ ///
+ /// Must call '{2}.{1}' before calling '{2}.{0}'.
+ ///
+ internal static string FormatScopeManager_EndCannotBeCalledWithoutACallToBegin(object p0, object p1, object p2)
+ {
+ return string.Format(CultureInfo.CurrentCulture, GetString("ScopeManager_EndCannotBeCalledWithoutACallToBegin"), p0, p1, p2);
+ }
+
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);
diff --git a/src/Microsoft.AspNet.Razor.Runtime/Resources.resx b/src/Microsoft.AspNet.Razor.Runtime/Resources.resx
index 8a7d783249..89259d17d4 100644
--- a/src/Microsoft.AspNet.Razor.Runtime/Resources.resx
+++ b/src/Microsoft.AspNet.Razor.Runtime/Resources.resx
@@ -128,4 +128,7 @@
Tag helper directive assembly name cannot be null or empty.
+
+ Must call '{2}.{1}' before calling '{2}.{0}'.
+
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelpersExecutionContext.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperExecutionContext.cs
similarity index 94%
rename from src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelpersExecutionContext.cs
rename to src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperExecutionContext.cs
index dd58d2c723..93087fab3b 100644
--- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelpersExecutionContext.cs
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperExecutionContext.cs
@@ -9,15 +9,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
///
/// Class used to store information about a 's execution lifetime.
///
- public class TagHelpersExecutionContext
+ public class TagHelperExecutionContext
{
private readonly List _tagHelpers;
///
- /// Instantiates a new .
+ /// Instantiates a new .
///
/// The HTML tag name in the Razor source.
- public TagHelpersExecutionContext([NotNull] string tagName)
+ public TagHelperExecutionContext([NotNull] string tagName)
{
AllAttributes = new Dictionary(StringComparer.Ordinal);
HTMLAttributes = new Dictionary(StringComparer.Ordinal);
diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperRunner.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperRunner.cs
index a6aa597529..fd8ba3c408 100644
--- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperRunner.cs
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperRunner.cs
@@ -17,7 +17,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// Contains information associated with running s.
/// Resulting from processing all of the
/// 's s.
- public async Task RunAsync([NotNull] TagHelpersExecutionContext context)
+ public async Task RunAsync([NotNull] TagHelperExecutionContext context)
{
return await RunAsyncCore(context, string.Empty);
}
@@ -29,13 +29,13 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// Contains the buffered content of the current HTML tag.
/// Resulting from processing all of the
/// 's s.
- public async Task RunAsync([NotNull] TagHelpersExecutionContext context,
+ public async Task RunAsync([NotNull] TagHelperExecutionContext context,
[NotNull] TextWriter bufferedBody)
{
return await RunAsyncCore(context, bufferedBody.ToString());
}
- private async Task RunAsyncCore(TagHelpersExecutionContext executionContext, string outputContent)
+ private async Task RunAsyncCore(TagHelperExecutionContext executionContext, string outputContent)
{
var tagHelperContext = new TagHelperContext(executionContext.AllAttributes);
var tagHelperOutput = new TagHelperOutput(executionContext.TagName,
diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperScopeManager.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperScopeManager.cs
new file mode 100644
index 0000000000..7ce38b69ba
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperScopeManager.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
+{
+ ///
+ /// Class that manages scopes.
+ ///
+ public class TagHelperScopeManager
+ {
+ private readonly Stack _executionScopes;
+
+ ///
+ /// Instantiates a new .
+ ///
+ public TagHelperScopeManager()
+ {
+ _executionScopes = new Stack();
+ }
+
+ ///
+ /// Starts a scope.
+ ///
+ /// The HTML tag name that the scope is associated with.
+ /// A to use.
+ public TagHelperExecutionContext Begin(string tagName)
+ {
+ var executionContext = new TagHelperExecutionContext(tagName);
+
+ _executionScopes.Push(executionContext);
+
+ return executionContext;
+ }
+
+ ///
+ /// Ends a scope.
+ ///
+ /// If the current scope is nested, the parent .
+ /// null otherwise.
+ public TagHelperExecutionContext End()
+ {
+ if (_executionScopes.Count == 0)
+ {
+ throw new InvalidOperationException(
+ Resources.FormatScopeManager_EndCannotBeCalledWithoutACallToBegin(
+ nameof(End),
+ nameof(Begin),
+ nameof(TagHelperScopeManager)));
+ }
+
+ _executionScopes.Pop();
+
+ if (_executionScopes.Count != 0)
+ {
+ return _executionScopes.Peek();
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file