I have this problem in my asp.net mvc application.
In one of my model there is a field "Description". The database column for this fields is set to NVarchar(300)
.
In my view I am creating a a text area as following.
@Html.TextAreaFor(m => m.Description, new { maxlength = "300" })
I am using "jquery.validate.unobtrusive.min.js" for client side validation. So when user types in the textarea and content length goes more than 300 characters it displays message "Please enter no more than 300 characaters."
Everything works fine till the following sceanario comes. User enters following data in the text area.
f
f
f
f
f
f
f
f
sdfa
(this content has 8 new lines)
According to "unobtrusive" validation this content has length 300 (counting each new line "\n" as a single character) so the validation passes and page posts back.
In my C# code, due to Encoding, the same content becomes fo length 308 (Counting each new line "\r\n" as 2 characters) which in tern fails the data base operation as it only allows 300 characters.
If someone is saying that I should have StringLength
attribute on this particular property, I have the following reason for not having it.
If I put this attribute the client-side validation does not happen for this particular property, it goes to the server and since the model is not valid it comes back to the page with error message.
Please advise me what could be the possible solution for this?
After taking a closer look at the solution by @Chris, I found that this would cause an endless loop for any control other than textarea with the @maxlength
attribute.
Furthermore, I found that using value
(=the value of the textarea passed into the validator) would already have the leading and trailing line breaks cut off, which means the database operation still failed when it tried to save text containing those line breaks.
So here is my solution:
(function ($) {
if ($.validator) {
//get the reference to the original function into a local variable
var _getLength = $.validator.prototype.getLength;
//overwrite existing getLength of validator
$.validator.prototype.getLength = function (value, element) {
//double count line breaks for textareas only
if (element.nodeName.toLowerCase() === 'textarea') {
//Counts all the newline characters (\r = return for macs, \r\n for Windows, \n for Linux/unix)
var newLineCharacterRegexMatch = /\r?\n|\r/g;
//use [element.value] rather than [value] since I found that the value passed in does cut off leading and trailing line breaks.
if (element.value) {
//count newline characters
var regexResult = element.value.match(newLineCharacterRegexMatch);
var newLineCount = regexResult ? regexResult.length : 0;
//replace newline characters with nothing
var replacedValue = element.value.replace(newLineCharacterRegexMatch, "");
//return the length of text without newline characters + doubled newline character count
return replacedValue.length + (newLineCount * 2);
} else {
return 0;
}
}
//call the original function reference with apply
return _getLength.apply(this, arguments);
};
}
})(jQuery);
I tested this in Chrome and a few IE versions and it worked fine for me.
You can change the behavior for getLength in client validation to double count newlines by adding the following to your javascript after you've included jquery.validate.js. This will cause the server-side and client-side length methods to match letting you use the StringLength attribute (I assume your issue with StringLength was that the server and client validation methods differed).
$.validator.prototype._getLength = $.validator.prototype.getLength;
$.validator.prototype.getLength = function (value, element) {
// Double count newlines in a textarea because they'll be turned into \r\n by the server.
if (element.nodeName.toLowerCase() === 'textarea')
return value.length + value.split('\n').length - 1;
return this._getLength(value, element);
};
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