From 7d1c1ed8eb37f8dcb345cd2b41317cdc8789157d Mon Sep 17 00:00:00 2001 From: damianedwards Date: Fri, 13 Mar 2015 12:31:02 -0700 Subject: [PATCH] Enable Tag Helper initializers: - Any Action 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 --- .../DefaultTagHelperActivator.cs | 19 +- .../ITagHelperActivator.cs | 5 +- .../ITagHelperInitializerOfT.cs | 24 +++ .../RazorServiceCollectionExtensions.cs | 24 +++ .../TagHelperInitializerOfT.cs | 31 +++ .../FormTagHelper.cs | 9 +- .../FormTagHelperOptions.cs | 21 --- .../ITagHelperOptionsCollection.cs | 18 -- .../TagHelperOptionsCollection.cs | 29 --- .../TagHelperOptionsCollectionExtensions.cs | 46 ----- .../TagHelperServiceCollectionExtensions.cs | 27 --- .../MvcTagHelpersTest.cs | 3 +- .../DefaultTagHelperActivatorTest.cs | 176 ++++++++++++++++++ .../RazorPageCreateTagHelperTest.cs | 9 + .../FormTagHelperTest.cs | 43 +---- ...agHelperOptionsCollectionExtensionsTest.cs | 52 ------ 16 files changed, 296 insertions(+), 240 deletions(-) create mode 100644 src/Microsoft.AspNet.Mvc.Razor/ITagHelperInitializerOfT.cs create mode 100644 src/Microsoft.AspNet.Mvc.Razor/TagHelperInitializerOfT.cs delete mode 100644 src/Microsoft.AspNet.Mvc.TagHelpers/FormTagHelperOptions.cs delete mode 100644 src/Microsoft.AspNet.Mvc.TagHelpers/ITagHelperOptionsCollection.cs delete mode 100644 src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOptionsCollection.cs delete mode 100644 src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOptionsCollectionExtensions.cs delete mode 100644 src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperServiceCollectionExtensions.cs create mode 100644 test/Microsoft.AspNet.Mvc.Razor.Test/DefaultTagHelperActivatorTest.cs delete mode 100644 test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOptionsCollectionExtensionsTest.cs diff --git a/src/Microsoft.AspNet.Mvc.Razor/DefaultTagHelperActivator.cs b/src/Microsoft.AspNet.Mvc.Razor/DefaultTagHelperActivator.cs index e9bdae6f93..33eafad47b 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/DefaultTagHelperActivator.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/DefaultTagHelperActivator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Reflection; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Razor.Runtime.TagHelpers; @@ -29,7 +30,8 @@ namespace Microsoft.AspNet.Mvc.Razor } /// - public void Activate([NotNull] ITagHelper tagHelper, [NotNull] ViewContext context) + public void Activate([NotNull] TTagHelper tagHelper, [NotNull] ViewContext context) + where TTagHelper : ITagHelper { var propertiesToActivate = _injectActions.GetOrAdd(tagHelper.GetType(), _getPropertiesToActivate); @@ -39,6 +41,21 @@ namespace Microsoft.AspNet.Mvc.Razor var activateInfo = propertiesToActivate[i]; activateInfo.Activate(tagHelper, context); } + + InitializeTagHelper(tagHelper, context); + } + + private static void InitializeTagHelper(TTagHelper tagHelper, ViewContext context) + where TTagHelper : ITagHelper + { + // Run any tag helper initializers in the container + var serviceProvider = context.HttpContext.RequestServices; + var initializers = serviceProvider.GetService>>(); + + foreach (var initializer in initializers) + { + initializer.Initialize(tagHelper, context); + } } private static PropertyActivator CreateActivateInfo(PropertyInfo property) diff --git a/src/Microsoft.AspNet.Mvc.Razor/ITagHelperActivator.cs b/src/Microsoft.AspNet.Mvc.Razor/ITagHelperActivator.cs index 892078f23e..2b9220d0df 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/ITagHelperActivator.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/ITagHelperActivator.cs @@ -13,8 +13,9 @@ namespace Microsoft.AspNet.Mvc.Razor /// /// When implemented in a type, activates an instantiated . /// - /// The to activate. + /// The type. + /// The to activate. /// The for the executing view. - void Activate(ITagHelper tagHelper, ViewContext context); + void Activate(TTagHelper tagHelper, ViewContext context) where TTagHelper : ITagHelper; } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/ITagHelperInitializerOfT.cs b/src/Microsoft.AspNet.Mvc.Razor/ITagHelperInitializerOfT.cs new file mode 100644 index 0000000000..34bf6da5f2 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Razor/ITagHelperInitializerOfT.cs @@ -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 +{ + /// + /// Initializes an before it's executed. + /// + /// The type. + public interface ITagHelperInitializer + where TTagHelper : ITagHelper + { + /// + /// Initializes the . + /// + /// The to initialize. + /// The for the executing view. + void Initialize([NotNull] TTagHelper helper, [NotNull] ViewContext context); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorServiceCollectionExtensions.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorServiceCollectionExtensions.cs index e120e5481d..d0318a4a8f 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorServiceCollectionExtensions.cs @@ -4,6 +4,7 @@ using System; using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.Razor; +using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.Framework.Internal; namespace Microsoft.Framework.DependencyInjection @@ -24,5 +25,28 @@ namespace Microsoft.Framework.DependencyInjection { services.Configure(setupAction); } + + /// + /// Adds an initialization callback for a given . + /// + /// + /// The callback will be invoked on any instance before the + /// method is called. + /// + /// The type of being initialized. + /// The instance this method extends. + /// An action to initialize the . + /// The instance this method extends. + public static IServiceCollection InitializeTagHelper( + [NotNull] this IServiceCollection services, + [NotNull] Action initialize) + where TTagHelper : ITagHelper + { + var initializer = new TagHelperInitializer(initialize); + + services.AddInstance(typeof(ITagHelperInitializer), initializer); + + return services; + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/TagHelperInitializerOfT.cs b/src/Microsoft.AspNet.Mvc.Razor/TagHelperInitializerOfT.cs new file mode 100644 index 0000000000..fcfeb4731a --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Razor/TagHelperInitializerOfT.cs @@ -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 +{ + /// + public class TagHelperInitializer : ITagHelperInitializer + where TTagHelper : ITagHelper + { + private readonly Action _initializeDelegate; + + /// + /// Creates a . + /// + /// The initialization delegate. + public TagHelperInitializer([NotNull] Action action) + { + _initializeDelegate = action; + } + + /// + public void Initialize([NotNull] TTagHelper helper, [NotNull] ViewContext context) + { + _initializeDelegate(helper, context); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/FormTagHelper.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/FormTagHelper.cs index 3c0b46d24c..4b24ecb609 100644 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/FormTagHelper.cs +++ b/src/Microsoft.AspNet.Mvc.TagHelpers/FormTagHelper.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Razor.Runtime.TagHelpers; -using Microsoft.Framework.OptionsModel; 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. [Activate] protected internal IHtmlGenerator Generator { get; set; } - - // Protected to ensure subclasses are correctly activated. Internal for ease of use when testing. - [Activate] - protected internal IOptions Options { get; set; } - + /// /// The name of the action method. /// @@ -113,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers } } - if (AntiForgery ?? Options.Options.GenerateAntiForgeryToken ?? antiForgeryDefault) + if (AntiForgery ?? antiForgeryDefault) { var antiForgeryTagBuilder = Generator.GenerateAntiForgery(ViewContext); if (antiForgeryTagBuilder != null) diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/FormTagHelperOptions.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/FormTagHelperOptions.cs deleted file mode 100644 index 34de7730b6..0000000000 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/FormTagHelperOptions.cs +++ /dev/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 -{ - /// - /// Options pertaining to the default behavior of instances. - /// - public class FormTagHelperOptions - { - /// - /// Whether the anti-forgery token should be generated by default for all instances of - /// . Can be overridden on any given instance. - /// - /// - /// Defaults to null, which indicates a token will only be generated if the action - /// attribute was not explicitly defined. - /// - public bool? GenerateAntiForgeryToken { get; set; } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/ITagHelperOptionsCollection.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/ITagHelperOptionsCollection.cs deleted file mode 100644 index 80e0f3646f..0000000000 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/ITagHelperOptionsCollection.cs +++ /dev/null @@ -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 -{ - /// - /// Used for adding options pertaining to s to an . - /// - public interface ITagHelperOptionsCollection - { - /// - /// The . - /// - IServiceCollection Services { get; } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOptionsCollection.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOptionsCollection.cs deleted file mode 100644 index a40f2155cb..0000000000 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOptionsCollection.cs +++ /dev/null @@ -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 -{ - /// - /// Used for adding options pertaining to s to an . - /// - public class TagHelperOptionsCollection : ITagHelperOptionsCollection - { - /// - /// Creates a new ; - /// - /// The instance to add the options to. - public TagHelperOptionsCollection([NotNull] IServiceCollection serviceCollection) - { - Services = serviceCollection; - } - - /// - /// The . - /// - public IServiceCollection Services { get; } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOptionsCollectionExtensions.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOptionsCollectionExtensions.cs deleted file mode 100644 index c673b09380..0000000000 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperOptionsCollectionExtensions.cs +++ /dev/null @@ -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 -{ - /// - /// Extension methods for . - /// - public static class TagHelperOptionsCollectionExtensions - { - /// - /// Configures options for the from an . - /// - /// The instance this method extends. - /// An to get the options from. - /// The . - public static ITagHelperOptionsCollection ConfigureForm( - [NotNull] this ITagHelperOptionsCollection collection, - [NotNull] IConfiguration configuration) - { - collection.Services.Configure(configuration); - - return collection; - } - - /// - /// Configures options for the using a delegate. - /// - /// The instance this method extends. - /// The options setup delegate. - /// The . - public static ITagHelperOptionsCollection ConfigureForm( - [NotNull] this ITagHelperOptionsCollection collection, - [NotNull] Action setupAction) - { - collection.Services.Configure(setupAction); - - return collection; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperServiceCollectionExtensions.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperServiceCollectionExtensions.cs deleted file mode 100644 index 0b694020a0..0000000000 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/TagHelperServiceCollectionExtensions.cs +++ /dev/null @@ -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 -{ - /// - /// Extension methods for . - /// - public static class TagHelperServiceCollectionExtensions - { - /// - /// Creates an which can be used to add options pertaining to - /// s to the . - /// - /// The instance this method extends. - /// The . - public static ITagHelperOptionsCollection ConfigureTagHelpers( - [NotNull] this IServiceCollection serviceCollection) - { - return new TagHelperOptionsCollection(serviceCollection); - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/MvcTagHelpersTest.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/MvcTagHelpersTest.cs index 8636620c3a..21faad73fa 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/MvcTagHelpersTest.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/MvcTagHelpersTest.cs @@ -10,6 +10,7 @@ using System.Net.Http.Headers; using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Mvc.TagHelpers; using Microsoft.Framework.DependencyInjection; using MvcTagHelpersWebSite; using Xunit; @@ -344,7 +345,7 @@ Products: Laptops (3)"; { // Arrange var newServices = new ServiceCollection(); - newServices.ConfigureTagHelpers().ConfigureForm(options => options.GenerateAntiForgeryToken = optionsAntiForgery); + newServices.InitializeTagHelper((helper, _) => helper.AntiForgery = optionsAntiForgery); var server = TestHelper.CreateServer(_app, SiteName, services => services.Add(newServices)); var client = server.CreateClient(); var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8"); diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/DefaultTagHelperActivatorTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/DefaultTagHelperActivatorTest.cs new file mode 100644 index 0000000000..c8fd9b35ff --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/DefaultTagHelperActivatorTest.cs @@ -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((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((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((h, vc) => + { + h.Name = "Test 1"; + h.Number = 100; + }); + services.InitializeTagHelper((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((h, vc) => + { + h.Name = "Test 1"; + h.Number = 100; + }); + services.InitializeTagHelper((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(), + viewData, + Mock.Of(), + 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; } + } + } +} diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageCreateTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageCreateTagHelperTest.cs index 0b5ec18c18..f50288305a 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageCreateTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageCreateTagHelperTest.cs @@ -2,7 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.ModelBinding; @@ -106,6 +108,13 @@ namespace Microsoft.AspNet.Mvc.Razor .Returns(myService); serviceProvider.Setup(mock => mock.GetService(typeof(ITagHelperActivator))) .Returns(new DefaultTagHelperActivator()); + serviceProvider.Setup(mock => mock.GetService(It.Is(serviceType => + serviceType.IsGenericType && serviceType.GetGenericTypeDefinition() == typeof(IEnumerable<>)))) + .Returns(serviceType => + { + var enumerableType = serviceType.GetGenericArguments().First(); + return typeof(Enumerable).GetMethod("Empty").MakeGenericMethod(enumerableType).Invoke(null, null); + }); var httpContext = new Mock(); httpContext.SetupGet(c => c.RequestServices) .Returns(serviceProvider.Object); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs index 006ed4a135..dfa085063f 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs @@ -90,22 +90,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers } [Theory] - [InlineData(null, true, "")] - [InlineData(null, false, "")] - [InlineData(null, null, "")] - [InlineData(true, true, "")] - [InlineData(true, false, "")] - [InlineData(true, null, "")] - [InlineData(false, true, "")] - [InlineData(false, false, "")] - [InlineData(false, null, "")] + [InlineData(null, "")] + [InlineData(true, "")] + [InlineData(false, "")] public async Task ProcessAsync_GeneratesAntiForgeryCorrectly( - bool? optionsAntiForgery, bool? antiForgery, string expectedPostContent) { // Arrange - var options = MakeOptions(new FormTagHelperOptions { GenerateAntiForgeryToken = optionsAntiForgery }); var viewContext = CreateViewContext(); var context = new TagHelperContext( allAttributes: new Dictionary(), @@ -139,7 +131,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Action = "Index", AntiForgery = antiForgery, Generator = generator.Object, - Options = options, ViewContext = viewContext, }; @@ -280,11 +271,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers public async Task ProcessAsync_RestoresBoundAttributesIfActionIsSpecified(string htmlAction) { // Arrange - var options = MakeOptions(); var formTagHelper = new FormTagHelper { - Method = "POST", - Options = options + Method = "POST" }; var output = new TagHelperOutput("form", attributes: new Dictionary @@ -323,22 +312,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers } [Theory] - [InlineData(null, true, "")] - [InlineData(null, false, "")] - [InlineData(null, null, "")] - [InlineData(true, true, "")] - [InlineData(true, false, "")] - [InlineData(true, null, "")] - [InlineData(false, true, "")] - [InlineData(false, false, "")] - [InlineData(false, null, "")] + [InlineData(true, "")] + [InlineData(false, "")] + [InlineData(null, "")] public async Task ProcessAsync_SupportsAntiForgeryIfActionIsSpecified( - bool? optionsAntiForgery, bool? antiForgery, string expectedPostContent) { // Arrange - var options = MakeOptions(new FormTagHelperOptions { GenerateAntiForgeryToken = optionsAntiForgery }); var viewContext = CreateViewContext(); var generator = new Mock(); @@ -348,7 +329,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { AntiForgery = antiForgery, Generator = generator.Object, - Options = options, ViewContext = viewContext, }; @@ -421,15 +401,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal(expectedErrorMessage, ex.Message); } - private static IOptions MakeOptions(TOptions options = null) - where TOptions : class, new() - { - var optionsAccessor = new Mock>(); - optionsAccessor.Setup(o => o.Options).Returns(options ?? new TOptions()); - - return optionsAccessor.Object; - } - private static ViewContext CreateViewContext() { var actionContext = new ActionContext( diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOptionsCollectionExtensionsTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOptionsCollectionExtensionsTest.cs deleted file mode 100644 index ebb59cebe4..0000000000 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOptionsCollectionExtensionsTest.cs +++ /dev/null @@ -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 - { - { "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 - { - { $"{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>().Options; - - // Assert - Assert.Equal(expectedValue, options.GenerateAntiForgeryToken); - } - } -} \ No newline at end of file