So könnten Sie vorgehen. Zunächst müssen Sie ein benutzerdefiniertes Validator-Attribut schreiben, um sicherzustellen, dass die Validierung auf der Serverseite erzwungen wird. Sie könnten das in diesem Artikel beschriebene Attribut verwenden Blogbeitrag :
public class CreditCardAttribute : ValidationAttribute, IClientValidatable
{
private CardType _cardTypes;
public CardType AcceptedCardTypes
{
get { return _cardTypes; }
set { _cardTypes = value; }
}
public CreditCardAttribute()
{
_cardTypes = CardType.All;
}
public CreditCardAttribute(CardType AcceptedCardTypes)
{
_cardTypes = AcceptedCardTypes;
}
public override bool IsValid(object value)
{
var number = Convert.ToString(value);
if (String.IsNullOrEmpty(number))
return true;
return IsValidType(number, _cardTypes) && IsValidNumber(number);
}
public override string FormatErrorMessage(string name)
{
return "The " + name + " field contains an invalid credit card number.";
}
public enum CardType
{
Unknown = 1,
Visa = 2,
MasterCard = 4,
Amex = 8,
Diners = 16,
All = CardType.Visa | CardType.MasterCard | CardType.Amex | CardType.Diners,
AllOrUnknown = CardType.Unknown | CardType.Visa | CardType.MasterCard | CardType.Amex | CardType.Diners
}
private bool IsValidType(string cardNumber, CardType cardType)
{
// Visa
if (Regex.IsMatch(cardNumber, "^(4)")
&& ((cardType & CardType.Visa) != 0))
return cardNumber.Length == 13 || cardNumber.Length == 16;
// MasterCard
if (Regex.IsMatch(cardNumber, "^(51|52|53|54|55)")
&& ((cardType & CardType.MasterCard) != 0))
return cardNumber.Length == 16;
// Amex
if (Regex.IsMatch(cardNumber, "^(34|37)")
&& ((cardType & CardType.Amex) != 0))
return cardNumber.Length == 15;
// Diners
if (Regex.IsMatch(cardNumber, "^(300|301|302|303|304|305|36|38)")
&& ((cardType & CardType.Diners) != 0))
return cardNumber.Length == 14;
//Unknown
if ((cardType & CardType.Unknown) != 0)
return true;
return false;
}
private bool IsValidNumber(string number)
{
int[] DELTAS = new int[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 0 };
int checksum = 0;
char[] chars = number.ToCharArray();
for (int i = chars.Length - 1; i > -1; i--)
{
int j = ((int)chars[i]) - 48;
checksum += j;
if (((i - chars.Length) % 2) == 0)
checksum += DELTAS[j];
}
return ((checksum % 10) == 0);
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage,
ValidationType = "creditcard"
};
}
}
Beachten Sie, dass ich es so verändert habe, dass es die IClientValidatable
Schnittstelle und fügte die GetClientValidationRules
Methode, die einfach dieselbe Fehlermeldung für die Client-Validierung wie auf der Serverseite verwendet und einen eindeutigen Namen für diesen Validator bereitstellt, der vom jquery unobtrusive adapter verwendet wird. Nun müssen Sie nur noch Ihre Modelleigenschaft mit diesem Attribut schmücken:
[CreditCard(ErrorMessage = "Please enter a valid credit card number")]
[Required]
public string CardNumber { get; set; }
und in Ihrer Sicht:
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
jQuery.validator.unobtrusive.adapters.addBool('creditcard');
});
</script>
@using (Html.BeginForm())
{
@Html.TextBoxFor(x => x.CardNumber)
@Html.ValidationMessageFor(x => x.CardNumber)
<input type="submit" value="OK" />
}