Added FormTagHelperOptions for configuring default behavior of FormTagHelper:
- #1689
This commit is contained in:
parent
a9feed4de1
commit
7c18e666a3
|
|
@ -6,6 +6,7 @@ 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,6 +29,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
[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<FormTagHelperOptions> Options { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the action method.
|
||||
/// </summary>
|
||||
|
|
@ -108,7 +113,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
}
|
||||
}
|
||||
|
||||
if (AntiForgery ?? antiForgeryDefault)
|
||||
if (AntiForgery ?? Options.Options.GenerateAntiForgeryToken ?? antiForgeryDefault)
|
||||
{
|
||||
var antiForgeryTagBuilder = Generator.GenerateAntiForgery(ViewContext);
|
||||
if (antiForgeryTagBuilder != null)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
// 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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// 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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.Net.Http;
|
||||
|
|
@ -13,15 +14,27 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
{
|
||||
public static string RetrieveAntiForgeryToken(string htmlContent, string actionUrl)
|
||||
{
|
||||
return RetrieveAntiForgeryTokens(
|
||||
htmlContent,
|
||||
attribute => attribute.Value.EndsWith(actionUrl, StringComparison.OrdinalIgnoreCase))
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IEnumerable<string> RetrieveAntiForgeryTokens(
|
||||
string htmlContent,
|
||||
Func<XAttribute, bool> predicate = null)
|
||||
{
|
||||
predicate = predicate ?? (_ => true);
|
||||
htmlContent = "<Root>" + htmlContent + "</Root>";
|
||||
var reader = new StringReader(htmlContent);
|
||||
var htmlDocument = XDocument.Load(reader);
|
||||
|
||||
foreach (var form in htmlDocument.Descendants("form"))
|
||||
{
|
||||
foreach (var attribute in form.Attributes())
|
||||
{
|
||||
if (string.Equals(attribute.Name.LocalName, "action", StringComparison.OrdinalIgnoreCase) &&
|
||||
attribute.Value.EndsWith(actionUrl, StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(attribute.Name.LocalName, "action", StringComparison.OrdinalIgnoreCase)
|
||||
&& predicate(attribute))
|
||||
{
|
||||
foreach (var input in form.Descendants("input"))
|
||||
{
|
||||
|
|
@ -30,14 +43,12 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
input.Attribute("name").Value == "__RequestVerificationToken" &&
|
||||
input.Attribute("type").Value == "hidden")
|
||||
{
|
||||
return input.Attributes("value").First().Value;
|
||||
yield return input.Attributes("value").First().Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string RetrieveAntiForgeryCookie(HttpResponseMessage response)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Form</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Form Tag Helper Test</h2>
|
||||
|
||||
<form action="/MvcTagHelper_Home/Form" method="post"></form>
|
||||
<form action="/MvcTagHelper_Home/Form" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
|
||||
<form action="/MvcTagHelper_Home/Form" method="post"></form>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Form</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Form Tag Helper Test</h2>
|
||||
|
||||
<form action="/MvcTagHelper_Home/Form" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
|
||||
<form action="/MvcTagHelper_Home/Form" method="post"><input name="__RequestVerificationToken" type="hidden" value="{1}" /></form>
|
||||
<form action="/MvcTagHelper_Home/Form" method="post"></form>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Form</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Form Tag Helper Test</h2>
|
||||
|
||||
<form action="/MvcTagHelper_Home/Form" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
|
||||
<form action="/MvcTagHelper_Home/Form" method="post"><input name="__RequestVerificationToken" type="hidden" value="{1}" /></form>
|
||||
<form action="/MvcTagHelper_Home/Form" method="post"></form>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -3,13 +3,18 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.TestHost;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Internal;
|
||||
using MvcTagHelpersWebSite;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -334,5 +339,41 @@ Products: Book1, Book2 (1)";
|
|||
Products: Laptops (3)";
|
||||
Assert.Equal(expected3, response4.Trim());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task FormTagHelper_GeneratesExpectedContent(bool? optionsAntiForgery)
|
||||
{
|
||||
// Arrange
|
||||
var newServices = new ServiceCollection();
|
||||
newServices.ConfigureTagHelpers().ConfigureForm(options => options.GenerateAntiForgeryToken = optionsAntiForgery);
|
||||
var serviceProvider = TestHelper.CreateServices("MvcTagHelpersWebSite", newServices);
|
||||
var server = TestServer.Create(serviceProvider, _app);
|
||||
var client = server.CreateClient();
|
||||
var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8");
|
||||
|
||||
// The K runtime compiles every file under compiler/resources as a resource at runtime with the same name
|
||||
// as the file name, in order to update a baseline you just need to change the file in that folder.
|
||||
var resourceName = string.Format(
|
||||
"compiler/resources/MvcTagHelpersWebSite.MvcTagHelper_Home.Form.Options.AntiForgery.{0}.html",
|
||||
optionsAntiForgery?.ToString() ?? "null"
|
||||
);
|
||||
var expectedContent = await _resourcesAssembly.ReadResourceAsStringAsync(resourceName);
|
||||
|
||||
// Act
|
||||
// The host is not important as everything runs in memory and tests are isolated from each other.
|
||||
var response = await client.GetAsync("http://localhost/MvcTagHelper_Home/Form");
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
|
||||
var forgeryTokens = AntiForgeryTestHelper.RetrieveAntiForgeryTokens(responseContent);
|
||||
expectedContent = string.Format(expectedContent, forgeryTokens.ToArray());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(expectedMediaType, response.Content.Headers.ContentType);
|
||||
Assert.Equal(expectedContent.Trim(), responseContent.Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
|
|||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -89,12 +90,22 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "<input />")]
|
||||
[InlineData(false, "")]
|
||||
[InlineData(null, "<input />")]
|
||||
public async Task ProcessAsync_GeneratesAntiForgeryCorrectly(bool? antiForgery, string expectedPostContent)
|
||||
[InlineData(null, true, "<input />")]
|
||||
[InlineData(null, false, "")]
|
||||
[InlineData(null, null, "<input />")]
|
||||
[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(
|
||||
bool? optionsAntiForgery,
|
||||
bool? antiForgery,
|
||||
string expectedPostContent)
|
||||
{
|
||||
// Arrange
|
||||
var options = MakeOptions(new FormTagHelperOptions { GenerateAntiForgeryToken = optionsAntiForgery });
|
||||
var viewContext = CreateViewContext();
|
||||
var context = new TagHelperContext(
|
||||
allAttributes: new Dictionary<string, object>(),
|
||||
|
|
@ -128,6 +139,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
Action = "Index",
|
||||
AntiForgery = antiForgery,
|
||||
Generator = generator.Object,
|
||||
Options = options,
|
||||
ViewContext = viewContext,
|
||||
};
|
||||
|
||||
|
|
@ -268,9 +280,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
public async Task ProcessAsync_RestoresBoundAttributesIfActionIsSpecified(string htmlAction)
|
||||
{
|
||||
// Arrange
|
||||
var options = MakeOptions<FormTagHelperOptions>();
|
||||
var formTagHelper = new FormTagHelper
|
||||
{
|
||||
Method = "POST"
|
||||
Method = "POST",
|
||||
Options = options
|
||||
};
|
||||
var output = new TagHelperOutput("form",
|
||||
attributes: new Dictionary<string, string>
|
||||
|
|
@ -309,14 +323,22 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "<input />")]
|
||||
[InlineData(false, "")]
|
||||
[InlineData(null, "")]
|
||||
[InlineData(null, true, "<input />")]
|
||||
[InlineData(null, false, "")]
|
||||
[InlineData(null, 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(
|
||||
bool? optionsAntiForgery,
|
||||
bool? antiForgery,
|
||||
string expectedPostContent)
|
||||
{
|
||||
// Arrange
|
||||
var options = MakeOptions(new FormTagHelperOptions { GenerateAntiForgeryToken = optionsAntiForgery });
|
||||
var viewContext = CreateViewContext();
|
||||
var generator = new Mock<IHtmlGenerator>();
|
||||
|
||||
|
|
@ -326,6 +348,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
{
|
||||
AntiForgery = antiForgery,
|
||||
Generator = generator.Object,
|
||||
Options = options,
|
||||
ViewContext = viewContext,
|
||||
};
|
||||
|
||||
|
|
@ -398,6 +421,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
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()
|
||||
{
|
||||
var actionContext = new ActionContext(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -166,5 +166,10 @@ namespace MvcTagHelpersWebSite.Controllers
|
|||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Form()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
@using Microsoft.Framework.DependencyInjection
|
||||
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Form</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Form Tag Helper Test</h2>
|
||||
|
||||
<form asp-controller="MvcTagHelper_Home" asp-action="Form"></form>
|
||||
<form asp-controller="MvcTagHelper_Home" asp-action="Form" asp-anti-forgery="true"></form>
|
||||
<form asp-controller="MvcTagHelper_Home" asp-action="Form" asp-anti-forgery="false"></form>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue