Print a useful error message when render-mode isn't specified (#15410)

* Print a useful error message when render-mode isn't specified
This commit is contained in:
Pranav K 2019-10-28 16:19:54 -07:00 committed by GitHub
commit 1361b0e5d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 4 deletions

View File

@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute("params", DictionaryAttributePrefix="param-")] [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute("params", DictionaryAttributePrefix="param-")]
public System.Collections.Generic.IDictionary<string, object> Parameters { get { throw null; } set { } } public System.Collections.Generic.IDictionary<string, object> Parameters { get { throw null; } set { } }
[Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute("render-mode")] [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.Mvc.ViewFeatures.ViewContextAttribute]
[Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute] [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute]
public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }

View File

@ -14,14 +14,16 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
/// <summary> /// <summary>
/// A <see cref="TagHelper"/> that renders a Razor component. /// A <see cref="TagHelper"/> that renders a Razor component.
/// </summary> /// </summary>
[HtmlTargetElement("component", Attributes = ComponentTypeName, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement(TagHelperName, Attributes = ComponentTypeName, TagStructure = TagStructure.WithoutEndTag)]
public sealed class ComponentTagHelper : TagHelper public sealed class ComponentTagHelper : TagHelper
{ {
private const string TagHelperName = "component";
private const string ComponentParameterName = "params"; private const string ComponentParameterName = "params";
private const string ComponentParameterPrefix = "param-"; private const string ComponentParameterPrefix = "param-";
private const string ComponentTypeName = "type"; private const string ComponentTypeName = "type";
private const string RenderModeName = "render-mode"; private const string RenderModeName = "render-mode";
private IDictionary<string, object> _parameters; private IDictionary<string, object> _parameters;
private RenderMode? _renderMode;
/// <summary> /// <summary>
/// Gets or sets the <see cref="Rendering.ViewContext"/> for the current request. /// Gets or sets the <see cref="Rendering.ViewContext"/> for the current request.
@ -54,7 +56,29 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
/// Gets or sets the <see cref="Rendering.RenderMode"/> /// Gets or sets the <see cref="Rendering.RenderMode"/>
/// </summary> /// </summary>
[HtmlAttributeName(RenderModeName)] [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));
}
}
}
/// <inheritdoc /> /// <inheritdoc />
public async override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) public async override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
@ -69,6 +93,11 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
throw new ArgumentNullException(nameof(output)); throw new ArgumentNullException(nameof(output));
} }
if (_renderMode is null)
{
throw new ArgumentException(Resources.FormatAttributeIsRequired(RenderModeName, TagHelperName), nameof(RenderMode));
}
var componentRenderer = ViewContext.HttpContext.RequestServices.GetRequiredService<IComponentRenderer>(); var componentRenderer = ViewContext.HttpContext.RequestServices.GetRequiredService<IComponentRenderer>();
var result = await componentRenderer.RenderComponentAsync(ViewContext, ComponentType, RenderMode, _parameters); var result = await componentRenderer.RenderComponentAsync(ViewContext, ComponentType, RenderMode, _parameters);

View File

@ -162,4 +162,7 @@
<data name="ViewEngine_FallbackViewNotFound" xml:space="preserve"> <data name="ViewEngine_FallbackViewNotFound" xml:space="preserve">
<value>The fallback partial view '{0}' was not found. The following locations were searched:{1}</value> <value>The fallback partial view '{0}' was not found. The following locations were searched:{1}</value>
</data> </data>
<data name="AttributeIsRequired" xml:space="preserve">
<value>A value for the '{0}' attribute must be supplied to the '{1}' tag helper.</value>
</data>
</root> </root>

View File

@ -3,13 +3,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO.Pipes;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Moq; using Moq;
using Xunit; using Xunit;
@ -25,6 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var tagHelper = new ComponentTagHelper var tagHelper = new ComponentTagHelper
{ {
ViewContext = GetViewContext(), ViewContext = GetViewContext(),
RenderMode = RenderMode.Static,
}; };
var context = GetTagHelperContext(); var context = GetTagHelperContext();
var output = GetTagHelperOutput(); var output = GetTagHelperOutput();
@ -38,6 +39,24 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
Assert.Null(output.TagName); 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() private static TagHelperContext GetTagHelperContext()
{ {
return new TagHelperContext( return new TagHelperContext(