diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs
index 18407ace88..6177a42729 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs
@@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlTargetElement("input", Attributes = ForAttributeName, TagStructure = TagStructure.WithoutEndTag)]
public class InputTagHelper : TagHelper
{
+ internal const string UseDateTimeLocalTypeForDateTimeOffsetSwitch = "Switch.Microsoft.AspNetCore.Mvc.UseDateTimeLocalTypeForDateTimeOffset";
private const string ForAttributeName = "asp-for";
private const string FormatAttributeName = "asp-format";
@@ -63,6 +64,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
{ "time", "{0:HH:mm:ss.fff}" },
};
+ static InputTagHelper()
+ {
+ if (AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled) && enabled)
+ {
+ _defaultInputTypes.Remove(nameof(DateTimeOffset));
+ }
+ }
+
///
/// Creates a new .
///
@@ -393,8 +402,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
{
// Rfc3339 mode _may_ override EditFormatString in a limited number of cases. Happens only when
// EditFormatString has a default format i.e. came from a [DataType] attribute.
+ //
+ // First condition may occur when Switch.Microsoft.AspNetCore.Mvc.UseDateTimeLocalTypeForDateTimeOffset
+ // is true in extremely rare cases: The element for a DateTimeOffset expression must have
+ // type ="text". Checking the switch again to remove that case.
if (string.Equals("text", inputType) &&
- string.Equals(nameof(DateTimeOffset), inputTypeHint, StringComparison.OrdinalIgnoreCase))
+ string.Equals(nameof(DateTimeOffset), inputTypeHint, StringComparison.OrdinalIgnoreCase) &&
+ !(AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled) &&
+ enabled))
{
// Auto-select a format that round-trips Offset and sub-Second values in a DateTimeOffset. Not
// done if user chose the "text" type in .cshtml file or with data annotations i.e. when
diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/TemplateRenderer.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/TemplateRenderer.cs
index 9ccc1cd361..a7a3073e1e 100644
--- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/TemplateRenderer.cs
+++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/TemplateRenderer.cs
@@ -17,9 +17,10 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
{
public class TemplateRenderer
{
+ public const string IEnumerableOfIFormFileName = "IEnumerable`" + nameof(IFormFile);
+ internal const string UseDateTimeLocalTypeForDateTimeOffsetSwitch = "Switch.Microsoft.AspNetCore.Mvc.UseDateTimeLocalTypeForDateTimeOffset";
private const string DisplayTemplateViewPath = "DisplayTemplates";
private const string EditorTemplateViewPath = "EditorTemplates";
- public const string IEnumerableOfIFormFileName = "IEnumerable`" + nameof(IFormFile);
private static readonly Dictionary> _defaultDisplayActions =
new Dictionary>(StringComparer.OrdinalIgnoreCase)
@@ -75,6 +76,14 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
private readonly string _templateName;
private readonly bool _readOnly;
+ static TemplateRenderer()
+ {
+ if (AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled) && enabled)
+ {
+ _defaultEditorActions.Remove(nameof(DateTimeOffset));
+ }
+ }
+
public TemplateRenderer(
IViewEngine viewEngine,
IViewBufferScope bufferScope,
diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/HtmlHelperOptionsTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/HtmlHelperOptionsTest.cs
index 76faef248d..855a4ae8ed 100644
--- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/HtmlHelperOptionsTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/HtmlHelperOptionsTest.cs
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. 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.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Testing;
@@ -10,6 +11,8 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
{
public class HtmlHelperOptionsTest : IClassFixture>
{
+ private const string UseDateTimeLocalTypeForDateTimeOffsetSwitch = "Switch.Microsoft.AspNetCore.Mvc.UseDateTimeLocalTypeForDateTimeOffset";
+
public HtmlHelperOptionsTest(MvcTestFixture fixture)
{
Client = fixture.Client;
@@ -21,14 +24,17 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
public async Task AppWideDefaultsInViewAndPartialView()
{
// Arrange
+ AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
+ var expectedType = enabled ? "datetime-local" : "text";
+ var expectedOffset = enabled ? string.Empty : "+00:00";
var expected =
-@"
MySummary
+$@"
MySummary
A model error occurred.
An error occurred.
-
+
MySummary
A model error occurred.
@@ -36,7 +42,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
An error occurred.
-
+
False";
@@ -52,14 +58,16 @@ False";
public async Task OverrideAppWideDefaultsInViewAndPartialView()
{
// Arrange
+ AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
+ var expectedType = enabled ? "datetime-local" : "text";
var expected =
-@"
MySummary
+$@"
MySummary
A model error occurred.
An error occurred.
-
+
True
MySummary
@@ -68,7 +76,7 @@ True
An error occurred.
-