[Fixes #2337] Added support for file types in input taghelper and
htmlhelper
This commit is contained in:
parent
a9f2c937df
commit
4951235eef
|
|
@ -8,6 +8,7 @@ using System.Globalization;
|
|||
using System.Text;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Internal;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ using System;
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Internal;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering
|
||||
{
|
||||
|
|
@ -374,6 +375,20 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
return GenerateTextBox(htmlHelper, inputType: "number");
|
||||
}
|
||||
|
||||
public static string FileInputTemplate([NotNull] IHtmlHelper htmlHelper)
|
||||
{
|
||||
return GenerateTextBox(htmlHelper, inputType: "file");
|
||||
}
|
||||
|
||||
public static string FileCollectionInputTemplate([NotNull] IHtmlHelper htmlHelper)
|
||||
{
|
||||
var htmlAttributes =
|
||||
CreateHtmlAttributes(htmlHelper, className: "text-box single-line", inputType: "file");
|
||||
htmlAttributes["multiple"] = "multiple";
|
||||
|
||||
return GenerateTextBox(htmlHelper, htmlHelper.ViewData.TemplateInfo.FormattedModelValue, htmlAttributes);
|
||||
}
|
||||
|
||||
private static void ApplyRfc3339DateFormattingIfNeeded(IHtmlHelper htmlHelper, string format)
|
||||
{
|
||||
if (htmlHelper.Html5DateRenderingMode != Html5DateRenderingMode.Rfc3339)
|
||||
|
|
@ -405,6 +420,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
var htmlAttributes =
|
||||
CreateHtmlAttributes(htmlHelper, className: "text-box single-line", inputType: inputType);
|
||||
|
||||
return GenerateTextBox(htmlHelper, value, htmlAttributes);
|
||||
}
|
||||
|
||||
private static string GenerateTextBox(IHtmlHelper htmlHelper, object value, object htmlAttributes)
|
||||
{
|
||||
return htmlHelper.TextBox(
|
||||
current: null,
|
||||
value: value,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNet.Mvc.Core;
|
|||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Expressions;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Internal;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ using System.Globalization;
|
|||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering
|
||||
namespace Microsoft.AspNet.Mvc.Rendering.Internal
|
||||
{
|
||||
internal class TemplateBuilder
|
||||
public class TemplateBuilder
|
||||
{
|
||||
private IViewEngine _viewEngine;
|
||||
private ViewContext _viewContext;
|
||||
|
|
@ -7,16 +7,19 @@ using System.Collections.Generic;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering
|
||||
namespace Microsoft.AspNet.Mvc.Rendering.Internal
|
||||
{
|
||||
internal class TemplateRenderer
|
||||
public class TemplateRenderer
|
||||
{
|
||||
private static readonly string DisplayTemplateViewPath = "DisplayTemplates";
|
||||
private static readonly string EditorTemplateViewPath = "EditorTemplates";
|
||||
private const string DisplayTemplateViewPath = "DisplayTemplates";
|
||||
private const string EditorTemplateViewPath = "EditorTemplates";
|
||||
public const string IEnumerableOfIFormFileName = "IEnumerable`" + nameof(IFormFile);
|
||||
|
||||
private static readonly Dictionary<string, Func<IHtmlHelper, string>> _defaultDisplayActions =
|
||||
new Dictionary<string, Func<IHtmlHelper, string>>(StringComparer.OrdinalIgnoreCase)
|
||||
|
|
@ -62,6 +65,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
{ typeof(decimal).Name, DefaultEditorTemplates.DecimalTemplate },
|
||||
{ typeof(string).Name, DefaultEditorTemplates.StringTemplate },
|
||||
{ typeof(object).Name, DefaultEditorTemplates.ObjectTemplate },
|
||||
{ typeof(IFormFile).Name, DefaultEditorTemplates.FileInputTemplate },
|
||||
{ IEnumerableOfIFormFileName, DefaultEditorTemplates.FileCollectionInputTemplate },
|
||||
};
|
||||
|
||||
private ViewContext _viewContext;
|
||||
|
|
@ -136,7 +141,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
metadata.DataTypeName
|
||||
};
|
||||
|
||||
foreach (string templateHint in templateHints.Where(s => !string.IsNullOrEmpty(s)))
|
||||
foreach (var templateHint in templateHints.Where(s => !string.IsNullOrEmpty(s)))
|
||||
{
|
||||
yield return templateHint;
|
||||
}
|
||||
|
|
@ -146,14 +151,27 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
var modelType = _viewData.ModelExplorer.ModelType;
|
||||
var fieldType = Nullable.GetUnderlyingType(modelType) ?? modelType;
|
||||
|
||||
yield return fieldType.Name;
|
||||
foreach (var typeName in GetTypeNames(_viewData.ModelExplorer.Metadata, fieldType))
|
||||
{
|
||||
yield return typeName;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetTypeNames(ModelMetadata modelMetadata, Type fieldType)
|
||||
{
|
||||
// Not returning type name here for IEnumerable<IFormFile> since we will be returning
|
||||
// a more specific name, IEnumerableOfIFormFileName.
|
||||
if (typeof(IEnumerable<IFormFile>) != fieldType)
|
||||
{
|
||||
yield return fieldType.Name;
|
||||
}
|
||||
|
||||
if (fieldType == typeof(string))
|
||||
{
|
||||
// Nothing more to provide
|
||||
yield break;
|
||||
}
|
||||
else if (!metadata.IsComplexType)
|
||||
else if (!modelMetadata.IsComplexType)
|
||||
{
|
||||
// IsEnum is false for the Enum class itself
|
||||
if (fieldType.IsEnum())
|
||||
|
|
@ -167,36 +185,44 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
}
|
||||
|
||||
yield return "String";
|
||||
yield break;
|
||||
}
|
||||
else if (fieldType.IsInterface())
|
||||
else if (!fieldType.IsInterface())
|
||||
{
|
||||
if (typeof(IEnumerable).IsAssignableFrom(fieldType))
|
||||
{
|
||||
yield return "Collection";
|
||||
}
|
||||
|
||||
yield return "Object";
|
||||
}
|
||||
else
|
||||
{
|
||||
var isEnumerable = typeof(IEnumerable).IsAssignableFrom(fieldType);
|
||||
|
||||
var type = fieldType;
|
||||
while (true)
|
||||
{
|
||||
fieldType = fieldType.BaseType();
|
||||
if (fieldType == null)
|
||||
type = type.BaseType();
|
||||
if (type == null || type == typeof(object))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (isEnumerable && fieldType == typeof(Object))
|
||||
{
|
||||
yield return "Collection";
|
||||
}
|
||||
|
||||
yield return fieldType.Name;
|
||||
yield return type.Name;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof(IEnumerable).IsAssignableFrom(fieldType))
|
||||
{
|
||||
if (typeof(IEnumerable<IFormFile>).IsAssignableFrom(fieldType))
|
||||
{
|
||||
yield return IEnumerableOfIFormFileName;
|
||||
|
||||
// Specific name has already been returned, now return the generic name.
|
||||
if (typeof(IEnumerable<IFormFile>) == fieldType)
|
||||
{
|
||||
yield return fieldType.Name;
|
||||
}
|
||||
}
|
||||
|
||||
yield return "Collection";
|
||||
}
|
||||
else if (typeof(IFormFile) != fieldType && typeof(IFormFile).IsAssignableFrom(fieldType))
|
||||
{
|
||||
yield return nameof(IFormFile);
|
||||
}
|
||||
|
||||
yield return "Object";
|
||||
}
|
||||
|
||||
private static IHtmlHelper MakeHtmlHelper(ViewContext viewContext, ViewDataDictionary viewData)
|
||||
|
|
@ -2,11 +2,12 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Internal;
|
||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||
|
|
@ -47,6 +48,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
{ nameof(Boolean), InputType.CheckBox.ToString().ToLowerInvariant() },
|
||||
{ nameof(Decimal), InputType.Text.ToString().ToLowerInvariant() },
|
||||
{ nameof(String), InputType.Text.ToString().ToLowerInvariant() },
|
||||
{ nameof(IFormFile), "file" },
|
||||
{ TemplateRenderer.IEnumerableOfIFormFileName, "file" },
|
||||
};
|
||||
|
||||
// Mapping from <input/> element's type to RFC 3339 date and time formats.
|
||||
|
|
@ -271,13 +274,22 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
format = GetFormat(modelExplorer, inputTypeHint, inputType);
|
||||
}
|
||||
|
||||
object htmlAttributes = null;
|
||||
if (string.Equals(inputType, "file") && string.Equals(inputTypeHint, TemplateRenderer.IEnumerableOfIFormFileName))
|
||||
{
|
||||
htmlAttributes = new Dictionary<string, object>
|
||||
{
|
||||
{ "multiple", "multiple" }
|
||||
};
|
||||
}
|
||||
|
||||
return Generator.GenerateTextBox(
|
||||
ViewContext,
|
||||
modelExplorer,
|
||||
For.Name,
|
||||
value: modelExplorer.Model,
|
||||
format: format,
|
||||
htmlAttributes: null);
|
||||
htmlAttributes: htmlAttributes);
|
||||
}
|
||||
|
||||
// Get a fall-back format based on the metadata.
|
||||
|
|
@ -353,55 +365,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
}
|
||||
}
|
||||
|
||||
yield return fieldType.Name;
|
||||
|
||||
if (fieldType == typeof(string))
|
||||
foreach (string typeName in TemplateRenderer.GetTypeNames(modelExplorer.Metadata, fieldType))
|
||||
{
|
||||
// Nothing more to provide
|
||||
yield break;
|
||||
}
|
||||
else if (!modelExplorer.Metadata.IsComplexType)
|
||||
{
|
||||
// IsEnum is false for the Enum class itself
|
||||
if (fieldType.IsEnum())
|
||||
{
|
||||
// Same as fieldType.BaseType.Name in this case
|
||||
yield return "Enum";
|
||||
}
|
||||
else if (fieldType == typeof(DateTimeOffset))
|
||||
{
|
||||
yield return "DateTime";
|
||||
}
|
||||
|
||||
yield return "String";
|
||||
}
|
||||
else if (fieldType.IsInterface())
|
||||
{
|
||||
if (typeof(IEnumerable).IsAssignableFrom(fieldType))
|
||||
{
|
||||
yield return "Collection";
|
||||
}
|
||||
|
||||
yield return "Object";
|
||||
}
|
||||
else
|
||||
{
|
||||
var isEnumerable = typeof(IEnumerable).IsAssignableFrom(fieldType);
|
||||
while (true)
|
||||
{
|
||||
fieldType = fieldType.BaseType();
|
||||
if (fieldType == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (isEnumerable && fieldType == typeof(Object))
|
||||
{
|
||||
yield return "Collection";
|
||||
}
|
||||
|
||||
yield return fieldType.Name;
|
||||
}
|
||||
yield return typeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Internal;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
|
|
@ -78,6 +80,9 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
{ "decimal", "__TextBox__ class='text-box single-line'" },
|
||||
{ "String", "__TextBox__ class='text-box single-line'" },
|
||||
{ "STRING", "__TextBox__ class='text-box single-line'" },
|
||||
{ typeof(IFormFile).Name, "__TextBox__ class='text-box single-line' type='file'" },
|
||||
{ TemplateRenderer.IEnumerableOfIFormFileName,
|
||||
"__TextBox__ class='text-box single-line' type='file' multiple='multiple'" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Http.Core.Collections;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering.Internal
|
||||
{
|
||||
public class TemplateRendererTest
|
||||
{
|
||||
public static TheoryData<Type, string[]> TypeNameData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<Type, string[]>
|
||||
{
|
||||
{ typeof(string), new string[] { "String" } },
|
||||
{ typeof(bool), new string[] { "Boolean", "String" } },
|
||||
{ typeof(DateTime), new string[] { "DateTime", "String" } },
|
||||
{ typeof(float), new string[] { "Single", "String" } },
|
||||
{ typeof(double), new string[] { "Double", "String" } },
|
||||
{ typeof(Guid), new string[] { "Guid", "String" } },
|
||||
{ typeof(TimeSpan), new string[] { "TimeSpan", "String" } },
|
||||
{ typeof(int), new string[] { "Int32", "String" } },
|
||||
{ typeof(ulong), new string[] { "UInt64", "String" } },
|
||||
|
||||
{ typeof(Enum), new string[] { "Enum", "String" } },
|
||||
{ typeof(HttpStatusCode), new string[] { "HttpStatusCode", "Enum", "String" } },
|
||||
|
||||
{ typeof(FormFile), new string[] { "FormFile", "IFormFile", "Object" } },
|
||||
{ typeof(IFormFile), new string[] { "IFormFile", "Object" } },
|
||||
|
||||
{ typeof(FormFileCollection), new string[] { "FormFileCollection", typeof(List<IFormFile>).Name,
|
||||
TemplateRenderer.IEnumerableOfIFormFileName, "Collection", "Object" } },
|
||||
{ typeof(IFormFileCollection), new string[] { "IFormFileCollection",
|
||||
TemplateRenderer.IEnumerableOfIFormFileName, "Collection", "Object" } },
|
||||
{ typeof(IEnumerable<IFormFile>), new string[] { TemplateRenderer.IEnumerableOfIFormFileName,
|
||||
typeof(IEnumerable<IFormFile>).Name, "Collection", "Object" } },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TypeNameData))]
|
||||
public void GetTypeNames_ReturnsExpectedResults(Type fieldType, string[] expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var metadataProvider = new TestModelMetadataProvider();
|
||||
var metadata = metadataProvider.GetMetadataForType(fieldType);
|
||||
|
||||
// Act
|
||||
var typeNames = TemplateRenderer.GetTypeNames(metadata, fieldType);
|
||||
|
||||
// Assert
|
||||
var collectionAssertions = expectedResult.Select<string, Action<string>>(expected =>
|
||||
actual => Assert.Equal(expected, actual));
|
||||
Assert.Collection(typeNames, collectionAssertions.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,6 +47,8 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
[InlineData("Link", null)]
|
||||
// Testing the ScriptTagHelper
|
||||
[InlineData("Script", null)]
|
||||
// Testing InputTagHelper with File
|
||||
[InlineData("Input", null)]
|
||||
public async Task MvcTagHelpers_GeneratesExpectedResults(string action, string antiForgeryPath)
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>File Input</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Input Tag Helper Test</h2>
|
||||
|
||||
<input name="InterfaceFile" type="file" id="InterfaceFile" value="" />
|
||||
<input name="InterfaceFiles" type="file" id="InterfaceFiles" multiple="multiple" value="" />
|
||||
<input name="ConcreteFile" type="file" id="ConcreteFile" value="" />
|
||||
<input name="ConcreteFiles" type="file" id="ConcreteFiles" multiple="multiple" value="" />
|
||||
<input name="EnumerableFiles" type="file" id="EnumerableFiles" multiple="multiple" value="" />
|
||||
|
||||
<input class="text-box single-line" id="InterfaceFile" name="InterfaceFile" type="file" value="" />
|
||||
<input class="text-box single-line" id="InterfaceFiles" multiple="multiple" name="InterfaceFiles" type="file" value="" />
|
||||
<input class="text-box single-line" id="ConcreteFile" name="ConcreteFile" type="file" value="" />
|
||||
<input class="text-box single-line" id="ConcreteFiles" multiple="multiple" name="ConcreteFiles" type="file" value="" />
|
||||
<input class="text-box single-line" id="EnumerableFiles" multiple="multiple" name="EnumerableFiles" type="file" value="" />
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,8 +5,10 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Internal;
|
||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
using Moq;
|
||||
|
|
@ -618,33 +620,48 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
Assert.Equal(expectedTagName, output.TagName);
|
||||
}
|
||||
|
||||
public static TheoryData<string, string, string> InputTypeData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<string, string, string>
|
||||
{
|
||||
{ null, null, "text" },
|
||||
{ "Byte", null, "number" },
|
||||
{ null, null, "text" },
|
||||
{ "Byte", null, "number" },
|
||||
{ "custom-datatype", null, "text" },
|
||||
{ "Custom-Datatype", null, "text" },
|
||||
{ "date", null, "date" }, // No date/time special cases since ModelType is string.
|
||||
{ "datetime", null, "datetime" },
|
||||
{ "datetime-local", null, "datetime-local" },
|
||||
{ "DATETIME-local", null, "datetime-local" },
|
||||
{ "Decimal", "{0:0.00}", "text" },
|
||||
{ "Double", null, "number" },
|
||||
{ "Int16", null, "number" },
|
||||
{ "Int32", null, "number" },
|
||||
{ "int32", null, "number" },
|
||||
{ "Int64", null, "number" },
|
||||
{ "SByte", null, "number" },
|
||||
{ "Single", null, "number" },
|
||||
{ "SINGLE", null, "number" },
|
||||
{ "string", null, "text" },
|
||||
{ "STRING", null, "text" },
|
||||
{ "text", null, "text" },
|
||||
{ "TEXT", null, "text" },
|
||||
{ "time", null, "time" },
|
||||
{ "UInt16", null, "number" },
|
||||
{ "uint16", null, "number" },
|
||||
{ "UInt32", null, "number" },
|
||||
{ "UInt64", null, "number" },
|
||||
{ nameof(IFormFile), null, "file" },
|
||||
{ TemplateRenderer.IEnumerableOfIFormFileName, null, "file" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, "text")]
|
||||
[InlineData("Byte", null, "number")]
|
||||
[InlineData("custom-datatype", null, "text")]
|
||||
[InlineData("Custom-Datatype", null, "text")]
|
||||
[InlineData("date", null, "date")] // No date/time special cases since ModelType is string.
|
||||
[InlineData("datetime", null, "datetime")]
|
||||
[InlineData("datetime-local", null, "datetime-local")]
|
||||
[InlineData("DATETIME-local", null, "datetime-local")]
|
||||
[InlineData("Decimal", "{0:0.00}", "text")]
|
||||
[InlineData("Double", null, "number")]
|
||||
[InlineData("Int16", null, "number")]
|
||||
[InlineData("Int32", null, "number")]
|
||||
[InlineData("int32", null, "number")]
|
||||
[InlineData("Int64", null, "number")]
|
||||
[InlineData("SByte", null, "number")]
|
||||
[InlineData("Single", null, "number")]
|
||||
[InlineData("SINGLE", null, "number")]
|
||||
[InlineData("string", null, "text")]
|
||||
[InlineData("STRING", null, "text")]
|
||||
[InlineData("text", null, "text")]
|
||||
[InlineData("TEXT", null, "text")]
|
||||
[InlineData("time", null, "time")]
|
||||
[InlineData("UInt16", null, "number")]
|
||||
[InlineData("uint16", null, "number")]
|
||||
[InlineData("UInt32", null, "number")]
|
||||
[InlineData("UInt64", null, "number")]
|
||||
[MemberData(nameof(InputTypeData))]
|
||||
public async Task ProcessAsync_CallsGenerateTextBox_AddsExpectedAttributes(
|
||||
string dataTypeName,
|
||||
string expectedFormat,
|
||||
|
|
@ -679,6 +696,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
metadataProvider: metadataProvider);
|
||||
|
||||
var tagBuilder = new TagBuilder("input", new HtmlEncoder());
|
||||
|
||||
Dictionary<string, object> htmlAttributes = null;
|
||||
if (string.Equals(dataTypeName, TemplateRenderer.IEnumerableOfIFormFileName))
|
||||
{
|
||||
htmlAttributes = new Dictionary<string, object>
|
||||
{
|
||||
{ "multiple", "multiple" }
|
||||
};
|
||||
}
|
||||
htmlGenerator
|
||||
.Setup(mock => mock.GenerateTextBox(
|
||||
tagHelper.ViewContext,
|
||||
|
|
@ -686,7 +712,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
tagHelper.For.Name,
|
||||
null, // value
|
||||
expectedFormat,
|
||||
null)) // htmlAttributes
|
||||
htmlAttributes)) // htmlAttributes
|
||||
.Returns(tagBuilder)
|
||||
.Verifiable();
|
||||
|
||||
|
|
|
|||
|
|
@ -171,5 +171,10 @@ namespace MvcTagHelpersWebSite.Controllers
|
|||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Input()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
// 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.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Http.Core.Collections;
|
||||
|
||||
namespace MvcTagHelpersWebSite.Models
|
||||
{
|
||||
public class Folder
|
||||
{
|
||||
public IFormFile InterfaceFile { get; set; }
|
||||
|
||||
public IFormFileCollection InterfaceFiles { get; set; }
|
||||
|
||||
public FormFile ConcreteFile { get; set; }
|
||||
|
||||
public FormFileCollection ConcreteFiles { get; set; }
|
||||
|
||||
public IEnumerable<IFormFile> EnumerableFiles { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
@using MvcTagHelpersWebSite.Models
|
||||
@model Folder
|
||||
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>File Input</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Input Tag Helper Test</h2>
|
||||
|
||||
<input asp-for="InterfaceFile" name="InterfaceFile" />
|
||||
<input asp-for="InterfaceFiles" name="InterfaceFiles" />
|
||||
<input asp-for="ConcreteFile" name="ConcreteFile" />
|
||||
<input asp-for="ConcreteFiles" name="ConcreteFiles" />
|
||||
<input asp-for="EnumerableFiles" name="EnumerableFiles" />
|
||||
|
||||
@Html.EditorFor(m => m.InterfaceFile)
|
||||
@Html.EditorFor(m => m.InterfaceFiles)
|
||||
@Html.EditorFor(m => m.ConcreteFile)
|
||||
@Html.EditorFor(m => m.ConcreteFiles)
|
||||
@Html.EditorFor(m => m.EnumerableFiles)
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue