Add ContentBehaviorAttribute for TagHelpers.

- Added detection of custom ContentBehaviors via the ContentBehaviorAttribute in the TagHelperDescriptorFactory.
- Updated some comments in the ContentBehavior enum.
- Add tests to validate custom content behavior resolution.

#122
This commit is contained in:
N. Taylor Mullen 2014-09-29 18:03:27 -07:00
parent d080dc8f71
commit ec638b147a
5 changed files with 93 additions and 14 deletions

View File

@ -0,0 +1,31 @@
// 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 Microsoft.AspNet.Razor.TagHelpers;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
/// <summary>
/// Used to override <see cref="ITagHelper"/>'s behavior when its
/// <see cref="ITagHelper.ProcessAsync"/> is invoked.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class ContentBehaviorAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="ContentBehaviorAttribute"/> class.
/// </summary>
/// <param name="contentBehavior">The <see cref="Razor.TagHelpers.ContentBehavior"/> for the
/// <see cref="ITagHelper"/>.</param>
public ContentBehaviorAttribute(ContentBehavior contentBehavior)
{
ContentBehavior = contentBehavior;
}
/// <summary>
/// <see cref="Razor.TagHelpers.ContentBehavior"/> for the <see cref="ITagHelper"/>.
/// </summary>
public ContentBehavior ContentBehavior { get; private set; }
}
}

View File

@ -66,10 +66,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
return new TagHelperAttributeDescriptor(property.Name, property);
}
// TODO: Make the content behavior pull from a ContentBehaviorAttribute: https://github.com/aspnet/Razor/issues/122
private static ContentBehavior GetContentBehavior(Type type)
{
return ContentBehavior.None;
var typeInfo = type.GetTypeInfo();
var contentBehaviorAttribute = typeInfo.GetCustomAttribute<ContentBehaviorAttribute>(inherit: false);
return contentBehaviorAttribute != null ?
contentBehaviorAttribute.ContentBehavior :
ContentBehavior.None;
}
private static bool IsValidProperty(PropertyInfo property)

View File

@ -5,6 +5,10 @@
},
"frameworks": {
"net45": { },
"aspnetcore50": { }
"aspnetcore50": {
"dependencies": {
"System.Reflection.Extensions": "4.0.0.0"
}
}
}
}

View File

@ -9,15 +9,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
public enum ContentBehavior
{
/// <summary>
/// Indicates that the tag helper will not modify its inner HTML in any way. This is the default
/// Indicates that a tag helper will not modify its content in any way. This is the default
/// <see cref="ContentBehavior"/>.
/// </summary>
/// <remarks>Children of the current tag helper will execute after the current tag helper.</remarks>
None,
/// <summary>
/// Indicates that the tag helper wants anything within its tag builder's inner HTML to be
/// appended to content its children generate.
/// Indicates the tag helper's content should be appended to what its children generate.
/// </summary>
/// <remarks>Children of the current tag helper will execute before the current tag helper.</remarks>
Append,
@ -30,15 +29,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
Modify,
/// <summary>
/// Indicates that the tag helper wants anything within its tag builder's inner HTML to be
/// prepended to the content its children generate.
/// Indicates the tag helper's content should be prepended to what its children generate.
/// </summary>
/// <remarks>Children of the current tag helper will execute after the current tag helper.</remarks>
Prepend,
/// <summary>
/// Indicates that the tag helper wants anything within its tag builder's inner HTML to
/// replace any HTML inside of it.
/// Indicates the tag helper's content should replace the HTML its children generate.
/// </summary>
/// <remarks>Children of the current tag helper will not execute.</remarks>
Replace,

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
public class TagHelperDescriptorFactoryTest
{
[Fact]
public void DescriptorFactory_BuildsDescriptorsFromSimpleTypes()
public void CreateDescriptor_BuildsDescriptorsFromSimpleTypes()
{
// Arrange
var expectedDescriptor = new TagHelperDescriptor("Object", "System.Object", ContentBehavior.None);
@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
[Fact]
public void DescriptorFactory_BuildsDescriptorsWithConventionNames()
public void CreateDescriptor_BuildsDescriptorsWithConventionNames()
{
// Arrange
var intProperty = typeof(SingleAttributeTagHelper).GetProperty(nameof(SingleAttributeTagHelper.IntAttribute));
@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
[Fact]
public void DescriptorFactory_OnlyAcceptsPropertiesWithGetAndSet()
public void CreateDescriptor_OnlyAcceptsPropertiesWithGetAndSet()
{
// Arrange
var validProperty = typeof(MissingAccessorTagHelper).GetProperty(
@ -63,7 +63,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
[Fact]
public void DescriptorFactory_OnlyAcceptsPropertiesWithPublicGetAndSet()
public void CreateDescriptor_OnlyAcceptsPropertiesWithPublicGetAndSet()
{
// Arrange
var validProperty = typeof(PrivateAccessorTagHelper).GetProperty(
@ -83,5 +83,48 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Assert
Assert.Equal(descriptor, expectedDescriptor, CompleteTagHelperDescriptorComparer.Default);
}
[Fact]
public void CreateDescriptor_ResolvesCustomContentBehavior()
{
// Arrange
var expectedDescriptor = new TagHelperDescriptor(
"CustomContentBehavior",
typeof(CustomContentBehaviorTagHelper).FullName,
ContentBehavior.Append);
// Act
var descriptor = TagHelperDescriptorFactory.CreateDescriptor(typeof(CustomContentBehaviorTagHelper));
// Assert
Assert.Equal(descriptor, expectedDescriptor, CompleteTagHelperDescriptorComparer.Default);
}
[Fact]
public void CreateDescriptor_DoesNotResolveInheritedCustomContentBehavior()
{
// Arrange
var expectedDescriptor = new TagHelperDescriptor(
"InheritedCustomContentBehavior",
typeof(InheritedCustomContentBehaviorTagHelper).FullName,
ContentBehavior.None);
// Act
var descriptor = TagHelperDescriptorFactory.CreateDescriptor(
typeof(InheritedCustomContentBehaviorTagHelper));
// Assert
Assert.Equal(descriptor, expectedDescriptor, CompleteTagHelperDescriptorComparer.Default);
}
[ContentBehavior(ContentBehavior.Append)]
private class CustomContentBehaviorTagHelper
{
}
private class InheritedCustomContentBehaviorTagHelper : CustomContentBehaviorTagHelper
{
}
}
}