Enable Tag Helper initializers:
- Any Action<ITagHelper, ViewContext> can be registered in DI to allow setting of tag helper properties after any [Activate] properties are set but before their bound from the source document and the tag helper is executed - Removed previous tag helper options as initializers is the way to do this now - #1689 - #2162
This commit is contained in:
parent
00feaaac29
commit
7d1c1ed8eb
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
|
@ -29,7 +30,8 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Activate([NotNull] ITagHelper tagHelper, [NotNull] ViewContext context)
|
public void Activate<TTagHelper>([NotNull] TTagHelper tagHelper, [NotNull] ViewContext context)
|
||||||
|
where TTagHelper : ITagHelper
|
||||||
{
|
{
|
||||||
var propertiesToActivate = _injectActions.GetOrAdd(tagHelper.GetType(),
|
var propertiesToActivate = _injectActions.GetOrAdd(tagHelper.GetType(),
|
||||||
_getPropertiesToActivate);
|
_getPropertiesToActivate);
|
||||||
|
|
@ -39,6 +41,21 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
var activateInfo = propertiesToActivate[i];
|
var activateInfo = propertiesToActivate[i];
|
||||||
activateInfo.Activate(tagHelper, context);
|
activateInfo.Activate(tagHelper, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InitializeTagHelper(tagHelper, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InitializeTagHelper<TTagHelper>(TTagHelper tagHelper, ViewContext context)
|
||||||
|
where TTagHelper : ITagHelper
|
||||||
|
{
|
||||||
|
// Run any tag helper initializers in the container
|
||||||
|
var serviceProvider = context.HttpContext.RequestServices;
|
||||||
|
var initializers = serviceProvider.GetService<IEnumerable<ITagHelperInitializer<TTagHelper>>>();
|
||||||
|
|
||||||
|
foreach (var initializer in initializers)
|
||||||
|
{
|
||||||
|
initializer.Initialize(tagHelper, context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PropertyActivator<ViewContext> CreateActivateInfo(PropertyInfo property)
|
private static PropertyActivator<ViewContext> CreateActivateInfo(PropertyInfo property)
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,9 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When implemented in a type, activates an instantiated <see cref="ITagHelper"/>.
|
/// When implemented in a type, activates an instantiated <see cref="ITagHelper"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tagHelper">The <see cref="ITagHelper"/> to activate.</param>
|
/// <typeparam name="TTagHelper">The <see cref="ITagHelper"/> type.</typeparam>
|
||||||
|
/// <param name="tagHelper">The <typeparamref name="TTagHelper"/> to activate.</param>
|
||||||
/// <param name="context">The <see cref="ViewContext"/> for the executing view.</param>
|
/// <param name="context">The <see cref="ViewContext"/> for the executing view.</param>
|
||||||
void Activate(ITagHelper tagHelper, ViewContext context);
|
void Activate<TTagHelper>(TTagHelper tagHelper, ViewContext context) where TTagHelper : ITagHelper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
// 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 Microsoft.AspNet.Mvc.Rendering;
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes an <see cref="ITagHelper"/> before it's executed.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TTagHelper">The <see cref="ITagHelper"/> type.</typeparam>
|
||||||
|
public interface ITagHelperInitializer<TTagHelper>
|
||||||
|
where TTagHelper : ITagHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the <typeparamref name="TTagHelper"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="helper">The <typeparamref name="TTagHelper"/> to initialize.</param>
|
||||||
|
/// <param name="context">The <see cref="ViewContext"/> for the executing view.</param>
|
||||||
|
void Initialize([NotNull] TTagHelper helper, [NotNull] ViewContext context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Mvc.Razor;
|
using Microsoft.AspNet.Mvc.Razor;
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
namespace Microsoft.Framework.DependencyInjection
|
namespace Microsoft.Framework.DependencyInjection
|
||||||
|
|
@ -24,5 +25,28 @@ namespace Microsoft.Framework.DependencyInjection
|
||||||
{
|
{
|
||||||
services.Configure(setupAction);
|
services.Configure(setupAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an initialization callback for a given <typeparamref name="TTagHelper"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The callback will be invoked on any <typeparamref name="TTagHelper"/> instance before the
|
||||||
|
/// <see cref="ITagHelper.ProcessAsync(TagHelperContext, TagHelperOutput)"/> method is called.
|
||||||
|
/// </remarks>
|
||||||
|
/// <typeparam name="TTagHelper">The type of <see cref="ITagHelper"/> being initialized.</typeparam>
|
||||||
|
/// <param name="services">The <see cref="IServiceCollection"/> instance this method extends.</param>
|
||||||
|
/// <param name="initialize">An action to initialize the <typeparamref name="TTagHelper"/>.</param>
|
||||||
|
/// <returns>The <see cref="IServiceCollection"/> instance this method extends.</returns>
|
||||||
|
public static IServiceCollection InitializeTagHelper<TTagHelper>(
|
||||||
|
[NotNull] this IServiceCollection services,
|
||||||
|
[NotNull] Action<TTagHelper, ViewContext> initialize)
|
||||||
|
where TTagHelper : ITagHelper
|
||||||
|
{
|
||||||
|
var initializer = new TagHelperInitializer<TTagHelper>(initialize);
|
||||||
|
|
||||||
|
services.AddInstance(typeof(ITagHelperInitializer<TTagHelper>), initializer);
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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.Runtime.TagHelpers;
|
||||||
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class TagHelperInitializer<TTagHelper> : ITagHelperInitializer<TTagHelper>
|
||||||
|
where TTagHelper : ITagHelper
|
||||||
|
{
|
||||||
|
private readonly Action<TTagHelper, ViewContext> _initializeDelegate;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="TagHelperInitializer{TTagHelper}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">The initialization delegate.</param>
|
||||||
|
public TagHelperInitializer([NotNull] Action<TTagHelper, ViewContext> action)
|
||||||
|
{
|
||||||
|
_initializeDelegate = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Initialize([NotNull] TTagHelper helper, [NotNull] ViewContext context)
|
||||||
|
{
|
||||||
|
_initializeDelegate(helper, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.Framework.OptionsModel;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -28,11 +27,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
|
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
|
||||||
[Activate]
|
[Activate]
|
||||||
protected internal IHtmlGenerator Generator { get; set; }
|
protected internal IHtmlGenerator Generator { get; set; }
|
||||||
|
|
||||||
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
|
|
||||||
[Activate]
|
|
||||||
protected internal IOptions<FormTagHelperOptions> Options { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the action method.
|
/// The name of the action method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -113,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AntiForgery ?? Options.Options.GenerateAntiForgeryToken ?? antiForgeryDefault)
|
if (AntiForgery ?? antiForgeryDefault)
|
||||||
{
|
{
|
||||||
var antiForgeryTagBuilder = Generator.GenerateAntiForgery(ViewContext);
|
var antiForgeryTagBuilder = Generator.GenerateAntiForgery(ViewContext);
|
||||||
if (antiForgeryTagBuilder != null)
|
if (antiForgeryTagBuilder != null)
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Options pertaining to the default behavior of <see cref="FormTagHelper"/> instances.
|
|
||||||
/// </summary>
|
|
||||||
public class FormTagHelperOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the anti-forgery token should be generated by default for all instances of
|
|
||||||
/// <see cref="FormTagHelper"/>. Can be overridden on any given instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// Defaults to <c>null</c>, which indicates a token will only be generated if the <c>action</c>
|
|
||||||
/// attribute was not explicitly defined.
|
|
||||||
/// </value>
|
|
||||||
public bool? GenerateAntiForgeryToken { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
// 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 Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
|
||||||
|
|
||||||
namespace Microsoft.Framework.DependencyInjection
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Used for adding options pertaining to <see cref="ITagHelper"/>s to an <see cref="IServiceCollection"/>.
|
|
||||||
/// </summary>
|
|
||||||
public interface ITagHelperOptionsCollection
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="IServiceCollection"/>.
|
|
||||||
/// </summary>
|
|
||||||
IServiceCollection Services { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
// 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 Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
|
||||||
using Microsoft.Framework.DependencyInjection;
|
|
||||||
using Microsoft.Framework.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Used for adding options pertaining to <see cref="ITagHelper"/>s to an <see cref="IServiceCollection"/>.
|
|
||||||
/// </summary>
|
|
||||||
public class TagHelperOptionsCollection : ITagHelperOptionsCollection
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new <see cref="TagHelperOptionsCollection"/>;
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="serviceCollection">The <see cref="IServiceCollection"/> instance to add the options to.</param>
|
|
||||||
public TagHelperOptionsCollection([NotNull] IServiceCollection serviceCollection)
|
|
||||||
{
|
|
||||||
Services = serviceCollection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="IServiceCollection"/>.
|
|
||||||
/// </summary>
|
|
||||||
public IServiceCollection Services { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
// 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.Mvc.TagHelpers;
|
|
||||||
using Microsoft.Framework.ConfigurationModel;
|
|
||||||
using Microsoft.Framework.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.Framework.DependencyInjection
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for <see cref="ITagHelperOptionsCollection"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static class TagHelperOptionsCollectionExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Configures options for the <see cref="FormTagHelper"/> from an <see cref="IConfiguration"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="collection">The <see cref="ITagHelperOptionsCollection"/> instance this method extends.</param>
|
|
||||||
/// <param name="configuration">An <see cref="IConfiguration"/> to get the options from.</param>
|
|
||||||
/// <returns>The <see cref="ITagHelperOptionsCollection"/>.</returns>
|
|
||||||
public static ITagHelperOptionsCollection ConfigureForm(
|
|
||||||
[NotNull] this ITagHelperOptionsCollection collection,
|
|
||||||
[NotNull] IConfiguration configuration)
|
|
||||||
{
|
|
||||||
collection.Services.Configure<FormTagHelperOptions>(configuration);
|
|
||||||
|
|
||||||
return collection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Configures options for the <see cref="FormTagHelper"/> using a delegate.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="collection">The <see cref="ITagHelperOptionsCollection"/> instance this method extends.</param>
|
|
||||||
/// <param name="setupAction">The options setup delegate.</param>
|
|
||||||
/// <returns>The <see cref="ITagHelperOptionsCollection"/>.</returns>
|
|
||||||
public static ITagHelperOptionsCollection ConfigureForm(
|
|
||||||
[NotNull] this ITagHelperOptionsCollection collection,
|
|
||||||
[NotNull] Action<FormTagHelperOptions> setupAction)
|
|
||||||
{
|
|
||||||
collection.Services.Configure(setupAction);
|
|
||||||
|
|
||||||
return collection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
// 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 Microsoft.AspNet.Mvc.TagHelpers;
|
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
|
||||||
using Microsoft.Framework.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.Framework.DependencyInjection
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for <see cref="IServiceCollection"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static class TagHelperServiceCollectionExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an <see cref="ITagHelperOptionsCollection"/> which can be used to add options pertaining to
|
|
||||||
/// <see cref="ITagHelper"/>s to the <see cref="IServiceCollection"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="serviceCollection">The <see cref="IServiceCollection"/> instance this method extends.</param>
|
|
||||||
/// <returns>The <see cref="ITagHelperOptionsCollection"/>.</returns>
|
|
||||||
public static ITagHelperOptionsCollection ConfigureTagHelpers(
|
|
||||||
[NotNull] this IServiceCollection serviceCollection)
|
|
||||||
{
|
|
||||||
return new TagHelperOptionsCollection(serviceCollection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -10,6 +10,7 @@ using System.Net.Http.Headers;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
|
using Microsoft.AspNet.Mvc.TagHelpers;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using MvcTagHelpersWebSite;
|
using MvcTagHelpersWebSite;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -344,7 +345,7 @@ Products: Laptops (3)";
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var newServices = new ServiceCollection();
|
var newServices = new ServiceCollection();
|
||||||
newServices.ConfigureTagHelpers().ConfigureForm(options => options.GenerateAntiForgeryToken = optionsAntiForgery);
|
newServices.InitializeTagHelper<FormTagHelper>((helper, _) => helper.AntiForgery = optionsAntiForgery);
|
||||||
var server = TestHelper.CreateServer(_app, SiteName, services => services.Add(newServices));
|
var server = TestHelper.CreateServer(_app, SiteName, services => services.Add(newServices));
|
||||||
var client = server.CreateClient();
|
var client = server.CreateClient();
|
||||||
var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8");
|
var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
// 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.IO;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Http.Core;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using Microsoft.AspNet.Routing;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
public class DefaultTagHelperActivatorTest
|
||||||
|
{
|
||||||
|
[Theory]
|
||||||
|
[InlineData("test", 100)]
|
||||||
|
[InlineData(null, -1)]
|
||||||
|
public void Activate_InitializesTagHelpers(string name, int number)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.InitializeTagHelper<TestTagHelper>((h, vc) =>
|
||||||
|
{
|
||||||
|
h.Name = name;
|
||||||
|
h.Number = number;
|
||||||
|
h.ViewDataValue = vc.ViewData["TestData"];
|
||||||
|
});
|
||||||
|
var httpContext = MakeHttpContext(services.BuildServiceProvider());
|
||||||
|
var viewContext = MakeViewContext(httpContext);
|
||||||
|
var viewDataValue = new object();
|
||||||
|
viewContext.ViewData.Add("TestData", viewDataValue);
|
||||||
|
var activator = new DefaultTagHelperActivator();
|
||||||
|
var helper = new TestTagHelper();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
activator.Activate(helper, viewContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(name, helper.Name);
|
||||||
|
Assert.Equal(number, helper.Number);
|
||||||
|
Assert.Same(viewDataValue, helper.ViewDataValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Activate_InitializesTagHelpersAfterActivatingProperties()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.InitializeTagHelper<TestTagHelper>((h, _) => h.ViewContext = MakeViewContext(MakeHttpContext()));
|
||||||
|
var httpContext = MakeHttpContext(services.BuildServiceProvider());
|
||||||
|
var viewContext = MakeViewContext(httpContext);
|
||||||
|
var activator = new DefaultTagHelperActivator();
|
||||||
|
var helper = new TestTagHelper();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
activator.Activate(helper, viewContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotSame(viewContext, helper.ViewContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Activate_InitializesTagHelpersWithMultipleInitializers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.InitializeTagHelper<TestTagHelper>((h, vc) =>
|
||||||
|
{
|
||||||
|
h.Name = "Test 1";
|
||||||
|
h.Number = 100;
|
||||||
|
});
|
||||||
|
services.InitializeTagHelper<TestTagHelper>((h, vc) =>
|
||||||
|
{
|
||||||
|
h.Name += ", Test 2";
|
||||||
|
h.Number += 100;
|
||||||
|
});
|
||||||
|
var httpContext = MakeHttpContext(services.BuildServiceProvider());
|
||||||
|
var viewContext = MakeViewContext(httpContext);
|
||||||
|
var activator = new DefaultTagHelperActivator();
|
||||||
|
var helper = new TestTagHelper();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
activator.Activate(helper, viewContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("Test 1, Test 2", helper.Name);
|
||||||
|
Assert.Equal(200, helper.Number);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Activate_InitializesTagHelpersWithCorrectInitializers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.InitializeTagHelper<TestTagHelper>((h, vc) =>
|
||||||
|
{
|
||||||
|
h.Name = "Test 1";
|
||||||
|
h.Number = 100;
|
||||||
|
});
|
||||||
|
services.InitializeTagHelper<AnotherTestTagHelper>((h, vc) =>
|
||||||
|
{
|
||||||
|
h.Name = "Test 2";
|
||||||
|
h.Number = 102;
|
||||||
|
});
|
||||||
|
var httpContext = MakeHttpContext(services.BuildServiceProvider());
|
||||||
|
var viewContext = MakeViewContext(httpContext);
|
||||||
|
var activator = new DefaultTagHelperActivator();
|
||||||
|
var testTagHelper = new TestTagHelper();
|
||||||
|
var anotherTestTagHelper = new AnotherTestTagHelper();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
activator.Activate(testTagHelper, viewContext);
|
||||||
|
activator.Activate(anotherTestTagHelper, viewContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("Test 1", testTagHelper.Name);
|
||||||
|
Assert.Equal(100, testTagHelper.Number);
|
||||||
|
Assert.Equal("Test 2", anotherTestTagHelper.Name);
|
||||||
|
Assert.Equal(102, anotherTestTagHelper.Number);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpContext MakeHttpContext(IServiceProvider services = null)
|
||||||
|
{
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
if (services != null)
|
||||||
|
{
|
||||||
|
httpContext.RequestServices = services;
|
||||||
|
}
|
||||||
|
return httpContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ViewContext MakeViewContext(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
||||||
|
var metadataProvider = new EmptyModelMetadataProvider();
|
||||||
|
var viewData = new ViewDataDictionary(metadataProvider);
|
||||||
|
var viewContext = new ViewContext(
|
||||||
|
actionContext,
|
||||||
|
Mock.Of<IView>(),
|
||||||
|
viewData,
|
||||||
|
Mock.Of<ITempDataDictionary>(),
|
||||||
|
TextWriter.Null);
|
||||||
|
|
||||||
|
return viewContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestTagHelper : TagHelper
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "Initial Name";
|
||||||
|
|
||||||
|
public int Number { get; set; } = 1000;
|
||||||
|
|
||||||
|
public object ViewDataValue { get; set; } = new object();
|
||||||
|
|
||||||
|
[Activate]
|
||||||
|
public ViewContext ViewContext { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AnotherTestTagHelper : TagHelper
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "Initial Name";
|
||||||
|
|
||||||
|
public int Number { get; set; } = 1000;
|
||||||
|
|
||||||
|
public object ViewDataValue { get; set; } = new object();
|
||||||
|
|
||||||
|
[Activate]
|
||||||
|
public ViewContext ViewContext { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
|
@ -106,6 +108,13 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
.Returns(myService);
|
.Returns(myService);
|
||||||
serviceProvider.Setup(mock => mock.GetService(typeof(ITagHelperActivator)))
|
serviceProvider.Setup(mock => mock.GetService(typeof(ITagHelperActivator)))
|
||||||
.Returns(new DefaultTagHelperActivator());
|
.Returns(new DefaultTagHelperActivator());
|
||||||
|
serviceProvider.Setup(mock => mock.GetService(It.Is<Type>(serviceType =>
|
||||||
|
serviceType.IsGenericType && serviceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))))
|
||||||
|
.Returns<Type>(serviceType =>
|
||||||
|
{
|
||||||
|
var enumerableType = serviceType.GetGenericArguments().First();
|
||||||
|
return typeof(Enumerable).GetMethod("Empty").MakeGenericMethod(enumerableType).Invoke(null, null);
|
||||||
|
});
|
||||||
var httpContext = new Mock<HttpContext>();
|
var httpContext = new Mock<HttpContext>();
|
||||||
httpContext.SetupGet(c => c.RequestServices)
|
httpContext.SetupGet(c => c.RequestServices)
|
||||||
.Returns(serviceProvider.Object);
|
.Returns(serviceProvider.Object);
|
||||||
|
|
|
||||||
|
|
@ -90,22 +90,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(null, true, "<input />")]
|
[InlineData(null, "<input />")]
|
||||||
[InlineData(null, false, "")]
|
[InlineData(true, "<input />")]
|
||||||
[InlineData(null, null, "<input />")]
|
[InlineData(false, "")]
|
||||||
[InlineData(true, true, "<input />")]
|
|
||||||
[InlineData(true, false, "")]
|
|
||||||
[InlineData(true, null, "<input />")]
|
|
||||||
[InlineData(false, true, "<input />")]
|
|
||||||
[InlineData(false, false, "")]
|
|
||||||
[InlineData(false, null, "")]
|
|
||||||
public async Task ProcessAsync_GeneratesAntiForgeryCorrectly(
|
public async Task ProcessAsync_GeneratesAntiForgeryCorrectly(
|
||||||
bool? optionsAntiForgery,
|
|
||||||
bool? antiForgery,
|
bool? antiForgery,
|
||||||
string expectedPostContent)
|
string expectedPostContent)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var options = MakeOptions(new FormTagHelperOptions { GenerateAntiForgeryToken = optionsAntiForgery });
|
|
||||||
var viewContext = CreateViewContext();
|
var viewContext = CreateViewContext();
|
||||||
var context = new TagHelperContext(
|
var context = new TagHelperContext(
|
||||||
allAttributes: new Dictionary<string, object>(),
|
allAttributes: new Dictionary<string, object>(),
|
||||||
|
|
@ -139,7 +131,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Action = "Index",
|
Action = "Index",
|
||||||
AntiForgery = antiForgery,
|
AntiForgery = antiForgery,
|
||||||
Generator = generator.Object,
|
Generator = generator.Object,
|
||||||
Options = options,
|
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -280,11 +271,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
public async Task ProcessAsync_RestoresBoundAttributesIfActionIsSpecified(string htmlAction)
|
public async Task ProcessAsync_RestoresBoundAttributesIfActionIsSpecified(string htmlAction)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var options = MakeOptions<FormTagHelperOptions>();
|
|
||||||
var formTagHelper = new FormTagHelper
|
var formTagHelper = new FormTagHelper
|
||||||
{
|
{
|
||||||
Method = "POST",
|
Method = "POST"
|
||||||
Options = options
|
|
||||||
};
|
};
|
||||||
var output = new TagHelperOutput("form",
|
var output = new TagHelperOutput("form",
|
||||||
attributes: new Dictionary<string, string>
|
attributes: new Dictionary<string, string>
|
||||||
|
|
@ -323,22 +312,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(null, true, "<input />")]
|
[InlineData(true, "<input />")]
|
||||||
[InlineData(null, false, "")]
|
[InlineData(false, "")]
|
||||||
[InlineData(null, null, "")]
|
[InlineData(null, "")]
|
||||||
[InlineData(true, true, "<input />")]
|
|
||||||
[InlineData(true, false, "")]
|
|
||||||
[InlineData(true, null, "<input />")]
|
|
||||||
[InlineData(false, true, "<input />")]
|
|
||||||
[InlineData(false, false, "")]
|
|
||||||
[InlineData(false, null, "")]
|
|
||||||
public async Task ProcessAsync_SupportsAntiForgeryIfActionIsSpecified(
|
public async Task ProcessAsync_SupportsAntiForgeryIfActionIsSpecified(
|
||||||
bool? optionsAntiForgery,
|
|
||||||
bool? antiForgery,
|
bool? antiForgery,
|
||||||
string expectedPostContent)
|
string expectedPostContent)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var options = MakeOptions(new FormTagHelperOptions { GenerateAntiForgeryToken = optionsAntiForgery });
|
|
||||||
var viewContext = CreateViewContext();
|
var viewContext = CreateViewContext();
|
||||||
var generator = new Mock<IHtmlGenerator>();
|
var generator = new Mock<IHtmlGenerator>();
|
||||||
|
|
||||||
|
|
@ -348,7 +329,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
AntiForgery = antiForgery,
|
AntiForgery = antiForgery,
|
||||||
Generator = generator.Object,
|
Generator = generator.Object,
|
||||||
Options = options,
|
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -421,15 +401,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Assert.Equal(expectedErrorMessage, ex.Message);
|
Assert.Equal(expectedErrorMessage, ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IOptions<TOptions> MakeOptions<TOptions>(TOptions options = null)
|
|
||||||
where TOptions : class, new()
|
|
||||||
{
|
|
||||||
var optionsAccessor = new Mock<IOptions<TOptions>>();
|
|
||||||
optionsAccessor.Setup(o => o.Options).Returns(options ?? new TOptions());
|
|
||||||
|
|
||||||
return optionsAccessor.Object;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ViewContext CreateViewContext()
|
private static ViewContext CreateViewContext()
|
||||||
{
|
{
|
||||||
var actionContext = new ActionContext(
|
var actionContext = new ActionContext(
|
||||||
|
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
// 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.Collections.Generic;
|
|
||||||
using Microsoft.Framework.ConfigurationModel;
|
|
||||||
using Microsoft.Framework.DependencyInjection;
|
|
||||||
using Microsoft.Framework.OptionsModel;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers.Test
|
|
||||||
{
|
|
||||||
public class TagHelperOptionsCollectionExtensionsTest
|
|
||||||
{
|
|
||||||
public static TheoryData ConfigureForm_GetsOptionsFromConfigurationCorrectly_Data
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new TheoryData<string, bool?>
|
|
||||||
{
|
|
||||||
{ "true", true },
|
|
||||||
{ "false", false },
|
|
||||||
{ "True", true },
|
|
||||||
{ "False", false },
|
|
||||||
{ "TRue", true },
|
|
||||||
{ "FAlse", false },
|
|
||||||
{ null, null }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(ConfigureForm_GetsOptionsFromConfigurationCorrectly_Data))]
|
|
||||||
public void ConfigureForm_GetsOptionsFromConfigurationCorrectly(string configValue, bool? expectedValue)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var configValues = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ $"{nameof(FormTagHelperOptions.GenerateAntiForgeryToken)}", configValue }
|
|
||||||
};
|
|
||||||
var config = new Configuration(new MemoryConfigurationSource(configValues));
|
|
||||||
var services = new ServiceCollection().AddOptions();
|
|
||||||
services.ConfigureTagHelpers().ConfigureForm(config);
|
|
||||||
var serviceProvider = services.BuildServiceProvider();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var options = serviceProvider.GetService<IOptions<FormTagHelperOptions>>().Options;
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(expectedValue, options.GenerateAntiForgeryToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue