Merge two `TypeExtensions` classes into Common\TypeExtensions.cs

- add missing `[NotNull]` attributes
- remove now-unneeded usings for ...ModelBinding.Internal namespace

Also get ModelBinding test project working under CoreCLR
- create separate k10 and net45 folders under test in VS
- add `[InternalsVisibleTo]` to make `TypeExtensions` visible to test assembly
- correct tests' `CultureInfo` use to compile under CoreCLR
- ifdef out CoreCLR tests depending on Moq, ReadOnly, ...
- remove a couple of tests expecting TypeConverter to work
This commit is contained in:
dougbu 2014-03-19 09:43:51 -07:00
parent 227121b3f9
commit 4bc7c36522
29 changed files with 283 additions and 236 deletions

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30313.0
VisualStudioVersion = 12.0.30110.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
EndProject
@ -55,6 +55,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestCommon.net45", "test\Te
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Mvc.Rendering.Test.net45", "test\Microsoft.AspNet.Mvc.Rendering.Test\Microsoft.AspNet.Mvc.Rendering.Test.net45.csproj", "{68FC3791-A9E4-4EDE-93A5-C7AC7DC0ED6E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "k10", "k10", "{A4E25DA1-9BC1-4534-BDAA-4AEB7C089B0F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "net45", "net45", "{49EBEEDD-E117-4B91-B4BA-56FB80AF4F3C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Mvc.ModelBinding.Test.k10", "test\Microsoft.AspNet.Mvc.ModelBinding.Test\Microsoft.AspNet.Mvc.ModelBinding.Test.k10.csproj", "{5A219830-3C19-475D-901F-E580BA87DFF8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -141,33 +147,40 @@ Global
{68FC3791-A9E4-4EDE-93A5-C7AC7DC0ED6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68FC3791-A9E4-4EDE-93A5-C7AC7DC0ED6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68FC3791-A9E4-4EDE-93A5-C7AC7DC0ED6E}.Release|Any CPU.Build.0 = Release|Any CPU
{5A219830-3C19-475D-901F-E580BA87DFF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5A219830-3C19-475D-901F-E580BA87DFF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A219830-3C19-475D-901F-E580BA87DFF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A219830-3C19-475D-901F-E580BA87DFF8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{365CA5C6-037D-4E6E-AF05-F5FA42E024EB} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{0D2C8C3D-AFC3-4E1F-A6D8-9F690EE5E063} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{A25566C9-97C7-4770-BBC1-9B815D3B1380} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{613579ED-7B96-4F5C-8DBF-D2C580257BE2} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{24947215-86AB-4DD0-B94E-88B1EC4DC877} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{28AA31B2-6504-432D-8599-1501FE0B100A} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{DA65D56F-1C40-4D38-B1E0-BF9641A98C52} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{236CDB04-8FDA-4152-9A5B-7F98C19C663A} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{6C2EDE5B-CA31-42DD-A352-84B10CC70C98} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{222CA408-93EE-473A-9325-D04989EC9FEF} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
{42195A56-42C0-4CFF-A982-B6E24EFC6356} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{537CC0EE-4B62-4789-9AE9-94BE28E0D25A} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{688ABC8B-BFA9-4CFF-9458-A466FEBB0448} = {222CA408-93EE-473A-9325-D04989EC9FEF}
{5E701B23-73E4-45D2-8521-1D7A94E152F1} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{6C2EDE5B-CA31-42DD-A352-84B10CC70C98} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{A25566C9-97C7-4770-BBC1-9B815D3B1380} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{28AA31B2-6504-432D-8599-1501FE0B100A} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{236CDB04-8FDA-4152-9A5B-7F98C19C663A} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{365CA5C6-037D-4E6E-AF05-F5FA42E024EB} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{792E181C-7645-4268-A04F-DB134411AD74} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{BA88E212-5889-48DC-823F-A3A67DDEF123} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{64BD92BA-F313-496C-ACE6-B9C4C10C420E} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{10142178-F784-4E17-A583-E9A37A80EFAA} = {6C2EDE5B-CA31-42DD-A352-84B10CC70C98}
{613579ED-7B96-4F5C-8DBF-D2C580257BE2} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{24947215-86AB-4DD0-B94E-88B1EC4DC877} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{DA65D56F-1C40-4D38-B1E0-BF9641A98C52} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{0D2C8C3D-AFC3-4E1F-A6D8-9F690EE5E063} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{5E701B23-73E4-45D2-8521-1D7A94E152F1} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{BA88E212-5889-48DC-823F-A3A67DDEF123} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{D4576205-A5B5-4382-BB34-19DE9855FE94} = {4EB70D0E-E27E-4C42-AB58-BC8B325EDFB3}
{3EB2CFF9-6E67-4C03-9AC4-2DD169024938} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{75A07B53-C5EE-4995-A55B-27562C23BCCD} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{68FC3791-A9E4-4EDE-93A5-C7AC7DC0ED6E} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{688ABC8B-BFA9-4CFF-9458-A466FEBB0448} = {222CA408-93EE-473A-9325-D04989EC9FEF}
{A4E25DA1-9BC1-4534-BDAA-4AEB7C089B0F} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{49EBEEDD-E117-4B91-B4BA-56FB80AF4F3C} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{5A219830-3C19-475D-901F-E580BA87DFF8} = {A4E25DA1-9BC1-4534-BDAA-4AEB7C089B0F}
{42195A56-42C0-4CFF-A982-B6E24EFC6356} = {49EBEEDD-E117-4B91-B4BA-56FB80AF4F3C}
{537CC0EE-4B62-4789-9AE9-94BE28E0D25A} = {49EBEEDD-E117-4B91-B4BA-56FB80AF4F3C}
{3EB2CFF9-6E67-4C03-9AC4-2DD169024938} = {49EBEEDD-E117-4B91-B4BA-56FB80AF4F3C}
{68FC3791-A9E4-4EDE-93A5-C7AC7DC0ED6E} = {49EBEEDD-E117-4B91-B4BA-56FB80AF4F3C}
{75A07B53-C5EE-4995-A55B-27562C23BCCD} = {49EBEEDD-E117-4B91-B4BA-56FB80AF4F3C}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,123 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Reflection;
namespace Microsoft.AspNet.Mvc
{
internal static class TypeExtensions
{
// NOTE: Do not make #105 worse! Do not add new extension methods that conflict w/ .NET 4.5 methods. The
// exising NETFX_CORE || K10 methods should go away (soon).
#if NETFX_CORE || K10
private static bool EqualTo([NotNull] this Type[] t1, [NotNull] Type[] t2)
{
if (t1.Length != t2.Length)
{
return false;
}
for (int idx = 0; idx < t1.Length; ++idx)
{
if (t1[idx] != t2[idx])
{
return false;
}
}
return true;
}
public static ConstructorInfo GetConstructor([NotNull] this Type type, Type[] types)
{
return type.GetTypeInfo().DeclaredConstructors
.Where(c => c.IsPublic)
.SingleOrDefault(c => c.GetParameters()
.Select(p => p.ParameterType).ToArray().EqualTo(types));
}
#endif
public static Type ExtractGenericInterface([NotNull] this Type queryType, Type interfaceType)
{
Func<Type, bool> matchesInterface = t => t.IsGenericType() && t.GetGenericTypeDefinition() == interfaceType;
return (matchesInterface(queryType)) ? queryType : queryType.GetInterfaces().FirstOrDefault(matchesInterface);
}
#if NETFX_CORE || K10
public static Type[] GetGenericArguments([NotNull] this Type type)
{
return type.GetTypeInfo().GenericTypeArguments;
}
public static Type[] GetInterfaces([NotNull] this Type type)
{
return type.GetTypeInfo().ImplementedInterfaces.ToArray();
}
public static bool IsAssignableFrom([NotNull] this Type type, [NotNull] Type c)
{
return type.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo());
}
#endif
public static bool IsGenericType([NotNull] this Type type)
{
return type.GetTypeInfo().IsGenericType;
}
public static bool IsInterface([NotNull] this Type type)
{
return type.GetTypeInfo().IsInterface;
}
public static bool IsValueType([NotNull] this Type type)
{
return type.GetTypeInfo().IsValueType;
}
public static bool IsCompatibleWith([NotNull] this Type type, object value)
{
return (value == null && AllowsNullValue(type)) ||
(value != null && type.GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo()));
}
public static bool IsNullableValueType([NotNull] this Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
public static bool AllowsNullValue([NotNull] this Type type)
{
return (!type.GetTypeInfo().IsValueType || IsNullableValueType(type));
}
public static bool HasStringConverter([NotNull] this Type type)
{
TypeInfo typeInfo = type.GetTypeInfo();
if (typeInfo.IsPrimitive || type == typeof(string))
{
return true;
}
if (IsNullableValueType(type) && HasStringConverter(type.GenericTypeArguments[0]))
{
// Nullable<T> where T is a primitive type or has a type converter
return true;
}
return false;
}
public static Type[] GetTypeArgumentsIfMatch([NotNull] Type closedType, Type matchingOpenType)
{
TypeInfo closedTypeInfo = closedType.GetTypeInfo();
if (!closedTypeInfo.IsGenericType)
{
return null;
}
Type openType = closedType.GetGenericTypeDefinition();
return (matchingOpenType == openType) ? closedTypeInfo.GenericTypeArguments : null;
}
}
}

View File

@ -1,6 +1,8 @@
{
"shared": "*.cs",
"dependencies": {
"System.Linq": "4.0.0.0",
"System.Reflection": "4.0.10.0",
"System.Runtime" : "4.0.20.0"
}
}

View File

@ -1,91 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Reflection;
namespace Microsoft.AspNet.Mvc
{
internal static class TypeExtensions
{
#if NETFX_CORE || K10
private static bool EqualTo(this Type[] t1, Type[] t2)
{
if (t1.Length != t2.Length)
{
return false;
}
for (int idx = 0; idx < t1.Length; ++idx)
{
if (t1[idx] != t2[idx])
{
return false;
}
}
return true;
}
public static ConstructorInfo GetConstructor(this Type type, Type[] types)
{
return type.GetTypeInfo().DeclaredConstructors
.Where(c => c.IsPublic)
.SingleOrDefault(c => c.GetParameters()
.Select(p => p.ParameterType).ToArray().EqualTo(types));
}
#endif
public static Type ExtractGenericInterface(this Type queryType, Type interfaceType)
{
Func<Type, bool> matchesInterface = t => t.IsGenericType() && t.GetGenericTypeDefinition() == interfaceType;
return (matchesInterface(queryType)) ? queryType : queryType.GetInterfaces().FirstOrDefault(matchesInterface);
}
#if NETFX_CORE || K10
public static Type[] GetGenericArguments(this Type type)
{
return type.GetTypeInfo().GenericTypeArguments;
}
public static Type[] GetInterfaces(this Type type)
{
return type.GetTypeInfo().ImplementedInterfaces.ToArray();
}
#endif
#if NETFX_CORE || K10
public static bool IsAssignableFrom(this Type type, Type c)
{
return type.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo());
}
#endif
public static bool IsGenericType(this Type type)
{
#if NETFX_CORE || K10
return type.GetTypeInfo().IsGenericType;
#else
return type.IsGenericType;
#endif
}
public static bool IsInterface(this Type type)
{
#if NETFX_CORE || K10
return type.GetTypeInfo().IsInterface;
#else
return type.IsInterface;
#endif
}
public static bool IsValueType(this Type type)
{
#if NETFX_CORE || K10
return type.GetTypeInfo().IsValueType;
#else
return type.IsValueType;
#endif
}
}
}

View File

@ -1,5 +1,4 @@
using Microsoft.AspNet.Mvc.ModelBinding.Internal;

namespace Microsoft.AspNet.Mvc.ModelBinding
{
public sealed class ComplexModelDtoResult

View File

@ -1,53 +0,0 @@
using System;
using System.Reflection;
namespace Microsoft.AspNet.Mvc.ModelBinding.Internal
{
public static class TypeExtensions
{
public static bool IsCompatibleWith([NotNull] this Type type, object value)
{
return (value == null && AllowsNullValue(type)) ||
(value != null && type.GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo()));
}
public static bool IsNullableValueType([NotNull] this Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
public static bool AllowsNullValue([NotNull] this Type type)
{
return (!type.GetTypeInfo().IsValueType || IsNullableValueType(type));
}
public static bool HasStringConverter([NotNull] this Type type)
{
// TODO: This depends on TypeConverter which does not exist in the CoreCLR.
// return TypeDescriptor.GetConverter(type).CanConvertFrom(typeof(string));
TypeInfo typeInfo = type.GetTypeInfo();
if (typeInfo.IsPrimitive || type == typeof(string))
{
return true;
}
if (IsNullableValueType(type) && HasStringConverter(type.GenericTypeArguments[0]))
{
// Nullable<T> where T is a primitive type or has a type converter
return true;
}
return false;
}
public static Type[] GetTypeArgumentsIfMatch([NotNull] Type closedType, Type matchingOpenType)
{
TypeInfo closedTypeInfo = closedType.GetTypeInfo();
if (!closedTypeInfo.IsGenericType)
{
return null;
}
Type openType = closedType.GetGenericTypeDefinition();
return (matchingOpenType == openType) ? closedTypeInfo.GenericTypeArguments : null;
}
}
}

View File

@ -0,0 +1,39 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Microsoft.AspNet.Mvc.ModelBinding")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Microsoft.AspNet.Mvc.ModelBinding")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8d29eb97-6f81-4304-86b1-adc94ffcff7d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Allow test assembly to access internals. This will stop working if we ever sign assemblies.
[assembly: InternalsVisibleTo("Microsoft.AspNet.Mvc.ModelBinding.Test")]

View File

@ -34,6 +34,7 @@
"System.Resources.ResourceManager": "4.0.0.0",
"System.Runtime": "4.0.20.0",
"System.Runtime.Extensions": "4.0.10.0",
"System.Runtime.InteropServices": "4.0.10.0",
"System.Threading": "4.0.0.0",
"System.Threading.Tasks": "4.0.0.0",
"System.Runtime.Serialization.Primitives": "4.0.0.0"

View File

@ -11,6 +11,7 @@
"System.Diagnostics.Debug": "4.0.10.0",
"System.Globalization": "4.0.10.0",
"System.IO": "4.0.0.0",
"System.Linq": "4.0.0.0",
"System.Reflection": "4.0.10.0",
"System.Resources.ResourceManager": "4.0.0.0",
"System.Runtime": "4.0.20.0",

View File

@ -18,6 +18,7 @@
"System.Dynamic.Runtime": "4.0.0.0",
"System.Globalization": "4.0.10.0",
"System.IO": "4.0.0.0",
"System.Linq": "4.0.0.0",
"System.Reflection": "4.0.10.0",
"System.Reflection.Extensions": "4.0.0.0",
"System.Resources.ResourceManager": "4.0.0.0",

View File

@ -19,6 +19,8 @@
"k10": {
"dependencies": {
"System.Diagnostics.Debug": "4.0.10.0",
"System.Linq": "4.0.0.0",
"System.Reflection": "4.0.10.0",
"System.Runtime": "4.0.20.0",
"System.Runtime.Extensions": "4.0.10.0"
}

View File

@ -1,4 +1,5 @@
using Moq;
#if NET45
using Moq;
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
@ -93,3 +94,4 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
}
}
#endif

View File

@ -1,13 +1,16 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
#if NET45
using Moq;
#endif
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
public class CollectionModelBinderTest
{
#if NET45
[Fact]
public void BindComplexCollectionFromIndexes_FiniteIndexes()
{
@ -88,6 +91,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Assert.True(retVal);
Assert.Equal(new[] { 42, 100, 200 }, ((List<int>)bindingContext.Model).ToArray());
}
#endif
[Fact]
public void BindSimpleCollection_RawValueIsEmptyCollection_ReturnsEmptyList()
@ -116,11 +120,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Assert.Null(boundCollection);
}
#if NET45
[Fact]
public void BindSimpleCollection_SubBindingSucceeds()
{
// Arrange
var culture = CultureInfo.GetCultureInfo("fr-FR");
var culture = new CultureInfo("fr-FR");
var bindingContext = GetModelBindingContext(new SimpleHttpValueProvider());
ModelValidationNode childValidationNode = null;
@ -174,5 +179,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
});
return mockIntBinder.Object;
}
#endif
}
}

View File

@ -1,4 +1,5 @@
using System;
#if NET45
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@ -228,3 +229,4 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
}
}
#endif

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
#if NET45
using System.Collections.Generic;
using Moq;
using Xunit;
@ -57,3 +58,4 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
}
}
#endif

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
#if NET45
using System.Collections.Generic;
using System.Linq;
using Moq;
using Xunit;
@ -156,3 +157,4 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
}
}
#endif

View File

@ -31,29 +31,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Assert.Equal("Input string was not in a correct format.", bindingContext.ModelState["theModelName"].Errors[0].ErrorMessage);
}
// TODO: TypeConverter
//[Fact]
//public void BindModel_Error_GeneralExceptionsSavedInModelState()
//{
// // Arrange
// ModelBindingContext bindingContext = GetBindingContext(typeof(Dummy));
// bindingContext.ValueProvider = new SimpleHttpValueProvider
// {
// { "theModelName", "foo" }
// };
// TypeConverterModelBinder binder = new TypeConverterModelBinder();
// // Act
// bool retVal = binder.BindModel(bindingContext);
// // Assert
// Assert.False(retVal);
// Assert.Null(bindingContext.Model);
// Assert.Equal("The parameter conversion from type 'System.String' to type 'Microsoft.AspNet.Mvc.ModelBinding.Test.TypeConverterModelBinderTest+Dummy' failed. See the inner exception for more information.", bindingContext.ModelState["theModelName"].Errors[0].Exception.Message);
// Assert.Equal("From DummyTypeConverter: foo", bindingContext.ModelState["theModelName"].Errors[0].Exception.InnerException.Message);
//}
[Fact]
public void BindModel_NullValueProviderResult_ReturnsFalse()
{
@ -121,24 +98,5 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ValueProvider = new SimpleHttpValueProvider() // empty
};
}
// TODO: TypeConverter
//[TypeConverter(typeof(DummyTypeConverter))]
//private struct Dummy
//{
//}
private sealed class DummyTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return (sourceType == typeof(string)) || base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
throw new InvalidOperationException(String.Format("From DummyTypeConverter: {0}", value));
}
}
}
}

View File

@ -2,7 +2,7 @@
using System.Collections.Generic;
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding.Internal.Test
namespace Microsoft.AspNet.Mvc
{
public class TypeExtensionTests
{

View File

@ -179,6 +179,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test.Binders
// "modelType");
//}
#if NET45 // No ReadOnlyAttribute in K
[Fact]
public void GetMetadataForTypeIncludesAttributesOnType()
{
@ -194,6 +195,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test.Binders
CreateMetadataPrototypeParams parms = provider.CreateMetadataPrototypeLog.Single(p => p.ModelType == typeof(TypeModel));
Assert.True(parms.Attributes.Any(a => a is ReadOnlyAttribute));
}
#endif
// Helpers
@ -227,10 +229,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test.Binders
public int ReadOnlyProperty { get; private set; }
}
#if NET45 // No [ReadOnly] in K
[ReadOnly(true)]
private class TypeModel
{
}
#endif
class TestableAssociatedMetadataProvider : AssociatedMetadataProvider<ModelMetadata>
{

View File

@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
#if NET45
using Moq;
#endif
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
@ -19,6 +21,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
"provider");
}
#if NET45
[Fact]
public void NullTypeThrows()
{
@ -51,6 +54,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Assert.Equal("propertyName", metadata.PropertyName);
Assert.False(metadata.IsReadOnly);
}
#endif
// IsComplexType
@ -58,6 +62,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
}
#if NET45
[Theory]
[InlineData(typeof(string))]
[InlineData(typeof(Nullable<int>))]
@ -127,6 +132,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Assert.Equal(propertyMetadata, result.ToList());
provider.Verify();
}
#endif
[Fact]
public void PropertiesListGetsResetWhenModelGetsReset()
@ -162,6 +168,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
// GetDisplayName()
#if NET45
[Fact]
public void ReturnsPropertyNameWhenSetAndDisplayNameIsNull()
{
@ -189,6 +196,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
// Assert
Assert.Equal("Object", result);
}
#endif
// Helpers

View File

@ -1,4 +1,5 @@
using System;
#if NET45
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
@ -109,3 +110,4 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
}
#endif

View File

@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
#if NET45
using Moq;
#endif
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding
@ -36,6 +38,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Default IValidatableObject adapter factory
#if NET45
[Fact]
public void IValidatableObjectGetsAValidator()
{
@ -50,6 +53,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Assert
Assert.Single(validators);
}
#endif
// Integration with metadata system

View File

@ -1,8 +1,10 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
#if NET45
using Moq;
using Moq.Protected;
#endif
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding
@ -56,6 +58,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
#if NET45
[Theory]
[MemberData("ValidateSetsMemberNamePropertyDataSet")]
public void ValidateSetsMemberNamePropertyOfValidationContextForProperties(ModelMetadata metadata, string expectedMemberName)
@ -199,6 +202,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ModelValidationResult validationResult = Assert.Single(results);
Assert.Equal("Name", validationResult.MemberName);
}
#endif
[Fact]
public void IsRequiredTests()

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
#if NET45
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
@ -56,3 +57,4 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
}
}
#endif

View File

@ -2,7 +2,9 @@
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
#if NET45
using Moq;
#endif
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
@ -18,6 +20,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ExceptionAssert.ThrowsArgumentNull(() => _factory.GetValueProviderAsync(requestContext: null), "requestContext");
}
#if NET45
[Fact]
public async Task GetValueProvider_ReturnsQueryStringValueProviderInstaceWithInvariantCulture()
{
@ -36,5 +39,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var valueProvider = Assert.IsType<ReadableStringCollectionValueProvider>(result);
Assert.Equal(CultureInfo.InvariantCulture, valueProvider.Culture);
}
#endif
}
}

View File

@ -162,7 +162,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public void GetValue_SingleValue()
{
// Arrange
var culture = CultureInfo.GetCultureInfo("fr-FR");
var culture = new CultureInfo("fr-FR");
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, culture);
// Act
@ -179,7 +179,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public void GetValue_MultiValue()
{
// Arrange
var culture = CultureInfo.GetCultureInfo("fr-FR");
var culture = new CultureInfo("fr-FR");
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, culture);
// Act
@ -200,7 +200,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
//public void GetValue_NullValue(string key)
//{
// // Arrange
// var culture = CultureInfo.GetCultureInfo("fr-FR");
// var culture = new CultureInfo("fr-FR");
// var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, culture);
// // Act
@ -222,7 +222,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
{ "key", new string[] { null, null, "value" } }
});
var culture = CultureInfo.GetCultureInfo("fr-FR");
var culture = new CultureInfo("fr-FR");
var valueProvider = new ReadableStringCollectionValueProvider(backingStore, culture);
// Act

View File

@ -26,7 +26,17 @@
},
"k10" : {
dependencies: {
"System.Collections": "4.0.0.0",
"System.ComponentModel": "4.0.0.0",
"System.Globalization": "4.0.10.0",
"System.Linq": "4.0.0.0",
"System.Reflection": "4.0.10.0",
"System.Runtime": "4.0.20.0",
"System.Runtime.Extensions": "4.0.10.0",
"System.Runtime.Serialization.Primitives": "4.0.0.0",
"System.Threading": "4.0.0.0",
"System.Threading.Tasks": "4.0.0.0",
"System.Threading.Thread": "4.0.0.0"
}
}
}

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNet.Mvc
{
private const string _defaultCultureName = "en-GB";
private const string _defaultUICultureName = "en-US";
private static readonly CultureInfo _defaultCulture = CultureInfo.GetCultureInfo(_defaultCultureName);
private static readonly CultureInfo _defaultCulture = new CultureInfo(_defaultCultureName);
private readonly CultureInfo _originalCulture;
private readonly CultureInfo _originalUICulture;
private readonly long _threadId;
@ -20,12 +20,12 @@ namespace Microsoft.AspNet.Mvc
// UICulture => Language
public CultureReplacer(string culture = _defaultCultureName, string uiCulture = _defaultUICultureName)
{
_originalCulture = Thread.CurrentThread.CurrentCulture;
_originalUICulture = Thread.CurrentThread.CurrentUICulture;
_originalCulture = CultureInfo.DefaultThreadCurrentCulture;
_originalUICulture = CultureInfo.DefaultThreadCurrentUICulture;
_threadId = Thread.CurrentThread.ManagedThreadId;
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(uiCulture);
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo(culture);
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(uiCulture);
}
/// <summary>
@ -62,9 +62,10 @@ namespace Microsoft.AspNet.Mvc
{
if (disposing)
{
Assert.True(Thread.CurrentThread.ManagedThreadId == _threadId, "The current thread is not the same as the thread invoking the constructor. This should never happen.");
Thread.CurrentThread.CurrentCulture = _originalCulture;
Thread.CurrentThread.CurrentUICulture = _originalUICulture;
Assert.True(Thread.CurrentThread.ManagedThreadId == _threadId,
"The current thread is not the same as the thread invoking the constructor. This should never happen.");
CultureInfo.DefaultThreadCurrentCulture = _originalCulture;
CultureInfo.DefaultThreadCurrentUICulture = _originalUICulture;
}
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.Globalization;
using System.Reflection;
using System.Threading;
using Xunit.Sdk;
namespace Microsoft.AspNet.Mvc
@ -14,7 +13,7 @@ namespace Microsoft.AspNet.Mvc
{
private const string _defaultCultureName = "en-GB";
private const string _defaultUICultureName = "en-US";
private static readonly CultureInfo _defaultCulture = CultureInfo.GetCultureInfo(_defaultCultureName);
private static readonly CultureInfo _defaultCulture = new CultureInfo(_defaultCultureName);
private CultureInfo _originalCulture;
private CultureInfo _originalUICulture;
@ -41,17 +40,17 @@ namespace Microsoft.AspNet.Mvc
public override void Before(MethodInfo methodUnderTest)
{
_originalCulture = Thread.CurrentThread.CurrentCulture;
_originalUICulture = Thread.CurrentThread.CurrentUICulture;
_originalCulture = CultureInfo.DefaultThreadCurrentCulture;
_originalUICulture = CultureInfo.DefaultThreadCurrentUICulture;
Thread.CurrentThread.CurrentCulture = Culture;
Thread.CurrentThread.CurrentUICulture = UICulture;
CultureInfo.DefaultThreadCurrentCulture = Culture;
CultureInfo.DefaultThreadCurrentUICulture = UICulture;
}
public override void After(MethodInfo methodUnderTest)
{
Thread.CurrentThread.CurrentCulture = _originalCulture;
Thread.CurrentThread.CurrentUICulture = _originalUICulture;
CultureInfo.DefaultThreadCurrentCulture = _originalCulture;
CultureInfo.DefaultThreadCurrentUICulture = _originalUICulture;
}
}
}