星期四, 11月 17, 2011

mvc3 自動加的 client 驗證

日前在處理mvc3 client的驗證問題,發現到如果在型別是int或是decimal等都會自動幫你加入驗證,這一點對Bibby我是蠻困擾的,Bibby驗證都是自己加的,自己來才是王道!下列就是mvc3"假伯"幫我們加的東西..

自動幫妳加入錯誤訊息
The field Money must be a number.

產生的html code

<label for="Money">Money</label>:
<input class="input-validation-error text-box single-line" data-val="true"
data-val-number="The field Money must be a number."
id="Money" name="Money" type="text" value="" />
<span class="field-validation-error" data-valmsg-for="Money" data-valmsg-replace="true">
A value is required.</span>

接下來就是尋找如何解決這ox的問題,找了一下發現原來是ClientDataTypeModelValidatorProvider幫我們加上去的,我們看一下source code

/* ****************************************************************************
*
* 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.Globalization;
using System.Linq;
using System.Web.Mvc.Resources;

public class ClientDataTypeModelValidatorProvider : ModelValidatorProvider {

private static readonly HashSet<Type> _numericTypes = new HashSet<Type>(new Type[] {
typeof(byte), typeof(sbyte),
typeof(short), typeof(ushort),
typeof(int), typeof(uint),
typeof(long), typeof(ulong),
typeof(float), typeof(double), typeof(decimal)
});

public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context) {
if (metadata == null) {
throw new ArgumentNullException("metadata");
}
if (context == null) {
throw new ArgumentNullException("context");
}

return GetValidatorsImpl(metadata, context);
}

private static IEnumerable<ModelValidator> GetValidatorsImpl(ModelMetadata metadata, ControllerContext context) {
Type type = metadata.ModelType;
if (IsNumericType(type)) {
yield return new NumericModelValidator(metadata, context);
}
}

private static bool IsNumericType(Type type) {
Type underlyingType = Nullable.GetUnderlyingType(type); // strip off the Nullable<>
return _numericTypes.Contains(underlyingType ?? type);
}

internal sealed class NumericModelValidator : ModelValidator {
public NumericModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
: base(metadata, controllerContext) {
}

public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
ModelClientValidationRule rule = new ModelClientValidationRule() {
ValidationType = "number",
ErrorMessage = MakeErrorString(Metadata.GetDisplayName())
};

return new ModelClientValidationRule[] { rule };
}

private static string MakeErrorString(string displayName) {
// use CurrentCulture since this message is intended for the site visitor
return String.Format(CultureInfo.CurrentCulture, MvcResources.ClientDataTypeModelValidatorProvider_FieldMustBeNumeric, displayName);
}

public override IEnumerable<ModelValidationResult> Validate(object container) {
// this is not a server-side validator
return Enumerable.Empty<ModelValidationResult>();
}
}

}
}

上面的code很清楚,在"那些"型別,都會幫你加上驗證,所以知道"人是誰殺的"那就閹掉他吧XD..解決方法請在Global.asax裡面加入下段的code

            var cdProvider = ModelValidatorProviders.Providers
.SingleOrDefault(p => p.GetType().Equals(typeof(ClientDataTypeModelValidatorProvider)));
if (cdProvider != null)
{
ModelValidatorProviders.Providers.Remove(cdProvider);
ModelValidatorProviders.Providers.Add(new CustomClientDataTypeModelValidatorProvider());
}

用借屍還魂的方式,再新增一個去代替內建的就可以了

    public class CustomClientDataTypeModelValidatorProvider : ModelValidatorProvider
{
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
return Enumerable.Empty<ModelValidator>();
}
}

就可以解決了,有問題在一起討論吧!

參考:
http://forums.asp.net/t/1512140.aspx/2/10

沒有留言: