1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This software is subject to the Microsoft Public License (Ms-PL).
* A copy of the license can be found in the license.htm file included
* in this distribution.
*
* You must not remove this notice, or any other, from this software.
*
* ***************************************************************************/
namespace System.Web.Mvc {
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Web.Mvc.Resources;
public delegate ModelValidator DataAnnotationsModelValidationFactory(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute);
public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider {
private static bool _addImplicitRequiredAttributeForValueTypes = true;
private static ReaderWriterLockSlim _adaptersLock = new ReaderWriterLockSlim();
internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory = DataAnnotationsModelValidator.Create;
internal static Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories = new Dictionary<Type, DataAnnotationsModelValidationFactory>() {
{
typeof(RangeAttribute),
(metadata, context, attribute) => new RangeAttributeAdapter(metadata, context, (RangeAttribute)attribute)
},
{
typeof(RegularExpressionAttribute),
(metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute)
},
{
typeof(RequiredAttribute),
(metadata, context, attribute) => new RequiredAttributeAdapter(metadata, context, (RequiredAttribute)attribute)
},
{
typeof(StringLengthAttribute),
(metadata, context, attribute) => new StringLengthAttributeAdapter(metadata, context, (StringLengthAttribute)attribute)
},
};
public static bool AddImplicitRequiredAttributeForValueTypes {
get {
return _addImplicitRequiredAttributeForValueTypes;
}
set {
_addImplicitRequiredAttributeForValueTypes = value;
}
}
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes) {
_adaptersLock.EnterReadLock();
try {
List<ModelValidator> results = new List<ModelValidator>();
if (AddImplicitRequiredAttributeForValueTypes &&
metadata.IsRequired &&
!attributes.Any(a => a is RequiredAttribute)) {
attributes = attributes.Concat(new[] { new RequiredAttribute() });
}
foreach (ValidationAttribute attribute in attributes.OfType<ValidationAttribute>()) {
DataAnnotationsModelValidationFactory factory;
if (!AttributeFactories.TryGetValue(attribute.GetType(), out factory)) {
factory = DefaultAttributeFactory;
}
results.Add(factory(metadata, context, attribute));
}
return results;
}
finally {
_adaptersLock.ExitReadLock();
}
}
public static void RegisterAdapter(Type attributeType, Type adapterType) {
ValidateAttributeType(attributeType);
ValidateAdapterType(adapterType);
ConstructorInfo constructor = GetAdapterConstructor(attributeType, adapterType);
_adaptersLock.EnterWriteLock();
try {
AttributeFactories[attributeType] = (metadata, context, attribute) => (ModelValidator)constructor.Invoke(new object[] { metadata, context, attribute });
}
finally {
_adaptersLock.ExitWriteLock();
}
}
public static void RegisterAdapterFactory(Type attributeType, DataAnnotationsModelValidationFactory factory) {
ValidateAttributeType(attributeType);
ValidateFactory(factory);
_adaptersLock.EnterWriteLock();
try {
AttributeFactories[attributeType] = factory;
}
finally {
_adaptersLock.ExitWriteLock();
}
}
public static void RegisterDefaultAdapter(Type adapterType) {
ValidateAdapterType(adapterType);
ConstructorInfo constructor = GetAdapterConstructor(typeof(ValidationAttribute), adapterType);
DefaultAttributeFactory = (metadata, context, attribute) => (ModelValidator)constructor.Invoke(new object[] { metadata, context, attribute });
}
public static void RegisterDefaultAdapterFactory(DataAnnotationsModelValidationFactory factory) {
ValidateFactory(factory);
DefaultAttributeFactory = factory;
}
// Helpers
private static ConstructorInfo GetAdapterConstructor(Type attributeType, Type adapterType) {
ConstructorInfo constructor = adapterType.GetConstructor(new[] { typeof(ModelMetadata), typeof(ControllerContext), attributeType });
if (constructor == null) {
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
MvcResources.DataAnnotationsModelValidatorProvider_ConstructorRequirements,
adapterType.FullName,
typeof(ModelMetadata).FullName,
typeof(ControllerContext).FullName,
attributeType.FullName
),
"adapterType"
);
}
return constructor;
}
private static void ValidateAdapterType(Type adapterType) {
if (adapterType == null) {
throw new ArgumentNullException("adapterType");
}
if (!typeof(ModelValidator).IsAssignableFrom(adapterType)) {
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
MvcResources.Common_TypeMustDriveFromType,
adapterType.FullName,
typeof(ModelValidator).FullName
),
"adapterType"
);
}
}
private static void ValidateAttributeType(Type attributeType) {
if (attributeType == null) {
throw new ArgumentNullException("attributeType");
}
if (!typeof(ValidationAttribute).IsAssignableFrom(attributeType)) {
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
MvcResources.Common_TypeMustDriveFromType,
attributeType.FullName,
typeof(ValidationAttribute).FullName
),
"attributeType");
}
}
private static void ValidateFactory(DataAnnotationsModelValidationFactory factory) {
if (factory == null) {
throw new ArgumentNullException("factory");
}
}
}
}
|