diff --git a/src/Mvc/Mvc.TagHelpers/ref/Microsoft.AspNetCore.Mvc.TagHelpers.netcoreapp.cs b/src/Mvc/Mvc.TagHelpers/ref/Microsoft.AspNetCore.Mvc.TagHelpers.netcoreapp.cs index ef7a542790..0523596d7e 100644 --- a/src/Mvc/Mvc.TagHelpers/ref/Microsoft.AspNetCore.Mvc.TagHelpers.netcoreapp.cs +++ b/src/Mvc/Mvc.TagHelpers/ref/Microsoft.AspNetCore.Mvc.TagHelpers.netcoreapp.cs @@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute("params", DictionaryAttributePrefix="param-")] public System.Collections.Generic.IDictionary Parameters { get { throw null; } set { } } [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute("render-mode")] - public Microsoft.AspNetCore.Mvc.Rendering.RenderMode RenderMode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public Microsoft.AspNetCore.Mvc.Rendering.RenderMode RenderMode { get { throw null; } set { } } [Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute] [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute] public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } diff --git a/src/Mvc/Mvc.TagHelpers/src/ComponentTagHelper.cs b/src/Mvc/Mvc.TagHelpers/src/ComponentTagHelper.cs index 6dc9bfe722..4bac5c8fc7 100644 --- a/src/Mvc/Mvc.TagHelpers/src/ComponentTagHelper.cs +++ b/src/Mvc/Mvc.TagHelpers/src/ComponentTagHelper.cs @@ -14,14 +14,16 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers /// /// A that renders a Razor component. /// - [HtmlTargetElement("component", Attributes = ComponentTypeName, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement(TagHelperName, Attributes = ComponentTypeName, TagStructure = TagStructure.WithoutEndTag)] public sealed class ComponentTagHelper : TagHelper { + private const string TagHelperName = "component"; private const string ComponentParameterName = "params"; private const string ComponentParameterPrefix = "param-"; private const string ComponentTypeName = "type"; private const string RenderModeName = "render-mode"; private IDictionary _parameters; + private RenderMode? _renderMode; /// /// Gets or sets the for the current request. @@ -54,7 +56,29 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers /// Gets or sets the /// [HtmlAttributeName(RenderModeName)] - public RenderMode RenderMode { get; set; } + public RenderMode RenderMode + { + get => _renderMode ?? default; + set + { + switch (value) + { + case RenderMode.Server: + case RenderMode.ServerPrerendered: + case RenderMode.Static: + _renderMode = value; + break; + + default: + throw new ArgumentException( + message: Resources.FormatInvalidEnumArgument( + nameof(value), + value, + typeof(RenderMode).FullName), + paramName: nameof(value)); + } + } + } /// public async override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) @@ -69,6 +93,11 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers throw new ArgumentNullException(nameof(output)); } + if (_renderMode is null) + { + throw new ArgumentException(Resources.FormatAttributeIsRequired(RenderModeName, TagHelperName), nameof(RenderMode)); + } + var componentRenderer = ViewContext.HttpContext.RequestServices.GetRequiredService(); var result = await componentRenderer.RenderComponentAsync(ViewContext, ComponentType, RenderMode, _parameters); diff --git a/src/Mvc/Mvc.TagHelpers/src/Resources.resx b/src/Mvc/Mvc.TagHelpers/src/Resources.resx index 96c56dff7f..7a69f0d95f 100644 --- a/src/Mvc/Mvc.TagHelpers/src/Resources.resx +++ b/src/Mvc/Mvc.TagHelpers/src/Resources.resx @@ -162,4 +162,7 @@ The fallback partial view '{0}' was not found. The following locations were searched:{1} + + A value for the '{0}' attribute must be supplied to the '{1}' tag helper. + \ No newline at end of file diff --git a/src/Mvc/Mvc.TagHelpers/test/ComponentTagHelperTest.cs b/src/Mvc/Mvc.TagHelpers/test/ComponentTagHelperTest.cs index 5c1aff4a7e..fe8db979bd 100644 --- a/src/Mvc/Mvc.TagHelpers/test/ComponentTagHelperTest.cs +++ b/src/Mvc/Mvc.TagHelpers/test/ComponentTagHelperTest.cs @@ -3,13 +3,13 @@ using System; using System.Collections.Generic; -using System.IO.Pipes; using System.Threading.Tasks; using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; using Moq; using Xunit; @@ -25,6 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers var tagHelper = new ComponentTagHelper { ViewContext = GetViewContext(), + RenderMode = RenderMode.Static, }; var context = GetTagHelperContext(); var output = GetTagHelperOutput(); @@ -38,6 +39,24 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers Assert.Null(output.TagName); } + [Fact] + public async Task ProcessAsync_WithoutSpecifyingRenderMode_ThrowsError() + { + // Arrange + var tagHelper = new ComponentTagHelper + { + ViewContext = GetViewContext(), + }; + var context = GetTagHelperContext(); + var output = GetTagHelperOutput(); + + // Act & Assert + await ExceptionAssert.ThrowsArgumentAsync( + () => tagHelper.ProcessAsync(context, output), + nameof(RenderMode), + "A value for the 'render-mode' attribute must be supplied to the 'component' tag helper."); + } + private static TagHelperContext GetTagHelperContext() { return new TagHelperContext(