1 namespace System.Web.Mvc {
2     using System;
3     using System.Collections.Generic;
4     using System.Globalization;
5     using System.Linq;
6     using System.Web.Mvc.Resources;
7 
8     public class ClientDataTypeModelValidatorProvider : ModelValidatorProvider {
9 
10         private static readonly HashSet<Type> _numericTypes = new HashSet<Type>(new Type[] {
11             typeof(byte), typeof(sbyte),
12             typeof(short), typeof(ushort),
13             typeof(int), typeof(uint),
14             typeof(long), typeof(ulong),
15             typeof(float), typeof(double), typeof(decimal)
16         });
17 
GetValidators(ModelMetadata metadata, ControllerContext context)18         public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context) {
19             if (metadata == null) {
20                 throw new ArgumentNullException("metadata");
21             }
22             if (context == null) {
23                 throw new ArgumentNullException("context");
24             }
25 
26             return GetValidatorsImpl(metadata, context);
27         }
28 
GetValidatorsImpl(ModelMetadata metadata, ControllerContext context)29         private static IEnumerable<ModelValidator> GetValidatorsImpl(ModelMetadata metadata, ControllerContext context) {
30             Type type = metadata.ModelType;
31             if (IsNumericType(type)) {
32                 yield return new NumericModelValidator(metadata, context);
33             }
34         }
35 
IsNumericType(Type type)36         private static bool IsNumericType(Type type) {
37             Type underlyingType = Nullable.GetUnderlyingType(type); // strip off the Nullable<>
38             return _numericTypes.Contains(underlyingType ?? type);
39         }
40 
41         internal sealed class NumericModelValidator : ModelValidator {
NumericModelValidator(ModelMetadata metadata, ControllerContext controllerContext)42             public NumericModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
43                 : base(metadata, controllerContext) {
44             }
45 
GetClientValidationRules()46             public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
47                 ModelClientValidationRule rule = new ModelClientValidationRule() {
48                     ValidationType = "number",
49                     ErrorMessage = MakeErrorString(Metadata.GetDisplayName())
50                 };
51 
52                 return new ModelClientValidationRule[] { rule };
53             }
54 
MakeErrorString(string displayName)55             private static string MakeErrorString(string displayName) {
56                 // use CurrentCulture since this message is intended for the site visitor
57                 return String.Format(CultureInfo.CurrentCulture, MvcResources.ClientDataTypeModelValidatorProvider_FieldMustBeNumeric, displayName);
58             }
59 
Validate(object container)60             public override IEnumerable<ModelValidationResult> Validate(object container) {
61                 // this is not a server-side validator
62                 return Enumerable.Empty<ModelValidationResult>();
63             }
64         }
65 
66     }
67 }
68