I have used the jquery validation plug in for a couple years now but this is my first effort to mixing with MVC 3 unobtrusive validation.
Information on the client side of things is scattered all over the internet and it's hard to find any thing that is deep enough to explain it to people that have not used it yet. I have been burning up Google for an hour now for an example on how to create a custom client side validator.
@Html.TextBoxFor(model => Model.CCPayment.CardNumber, new { @class = "textInput validateCreditCard", maxLength = "20" })
$(document).ready(function () {
jQuery.validator.unobtrusive.adapters.add('validateCreditCard', {}, function (value, element) {
alert('foo');
});
});
if I run the above code in the bottom of my view it does absolutely nothing. I have even tried jquery.validator.addmethod() and still nothing. All the client side validation that is emitted from my model validation annotations works fine.
<div class="ctrlHolder">
<label>
<em>*</em>
Card Number:
</label>
@Html.TextBoxFor(model => Model.CCPayment.CardNumber, new { @class = "textInput validateCreditCard", maxLength = "20" })
<p class="field-validation-valid formHint" data-valmsg-for="CCPayment.CardNumber"></p>
</div>
Firstly, you just need to create an ASP.NET MVC application. To create a new ASP.NET MVC application, Open Visual Studio choose File, New, then Project. It will open a New Project window, from where you need to choose node Visual C# and then Web and from the right pane you need to choose ASP.NET Web Application.
An unobtrusive validation in jQuery is a set of ASP.Net MVC HTML helper extensions.By using jQuery Validation data attributes along with HTML 5 data attributes, you can perform validation to the client-side.
Here's how you could proceed. First you need to write a custom validator attribute in order to ensure that the validation is enforced on the server side. You could use the one described in this blog post:
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"
};
}
}
Notice that I've modified it to make it implement the IClientValidatable
interface and added the GetClientValidationRules
method which simply uses the same error message for client validation as the server side and provides an unique name for this validator that will be used by the jquery unobtrusive adapter. Now all that's left is to decorate your model property with this attribute:
[CreditCard(ErrorMessage = "Please enter a valid credit card number")]
[Required]
public string CardNumber { get; set; }
and in your view:
<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" />
}
You need ValidateFor
in addition to TextBoxFor
. I can't tell from your question if you've already done that or not. You also need EnableClientValidation
before the form.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With