jQuery validate textarea maxlength bug
I'm using jQuery.validate v 1.6.0 to validate my forms.
One of my database fields is limited to 1000 chars. I added a validation to the corresponding textarea like this:
In the header of my page, I add
$('form.validate').validate();
Inside my page, I 开发者_StackOverflow社区declare:
<form method="post" class="validate" action="Save">
<textarea name="description" minlength="15" maxlength="1000" id="description" class="required"></textarea>
<input type="submit" value="Save">
</form>
The issue I'm encountering is that jQuery seems to count the number of chars involved in a 'new line' differently as my database.
When I type exactly 1000 chars without new lines, all goes well, and the validation works. If I type 1000 chars with some new lines, jQuery allows the POST to happen, but my database refuses the insert/update, because the data is too big.
Any hints would be appreciated.
I came a cross this perticular problem using jQuery Validate 1.9. Because I'm using ASP.NET MVC 3 and C# on the server line breaks was "\r\n" on the server but "\n" on the client. When I validated my textarea on the client the validation did not fail because "\n" is just counted as one character but when the text went to validation on the server where linebreaks are "\r\n" the validation would fail.
My soultion to this problem was to override jQuery validation method "rangelengt" because i also have a minimum length defined:
$.validator.addMethod('rangelength', function (value, element) {
var maxlen = parseInt($(element).attr('data-val-length-max'));
if (maxlen > 0) {
var remaining = (maxlen - (parseInt($(element).val().replace(/(\r\n|\n|\r)/gm, '\r\n').length)));
if (remaining < 0) {
return false;
}
}
return true;
});
So what this code actually does is to get the maxlength value and then get the value from the element and then it replaces all "\n" characters with "\r\n" to get the same count of characters as the server would.
I also took the server-side approach, like John Bubriski did, but implemented it in ASP.NET MVC as an extension to the DefaultModelBinder, so that all controller actions will benefit immediately:
public class NewlinesNormalizingModelBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
{
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
// Note: if desired, one could restrict the conversion to properties decorated with [StringLength]:
// && propertyDescriptor.Attributes.OfType<StringLengthAttribute>().Any()
if (propertyDescriptor.PropertyType == typeof(string))
{
var originalString = propertyDescriptor.GetValue(bindingContext.Model) as string;
if (!string.IsNullOrEmpty(originalString))
{
var stringWithNormalizedNewlines = originalString.Replace("\r\n", "\n");
propertyDescriptor.SetValue(bindingContext.Model, stringWithNormalizedNewlines);
}
}
}
}
Then upon application startup:
ModelBinders.Binders.DefaultBinder = new NewlinesNormalizingModelBinder();
While this isn't a client side solution, I was able to handle the problem server side.
I basically strip out the "extra" characters which are the "\r" characters. I guess these don't count towards the string length in the browser, or they get combined as one with the "\n" characters.
In my case, ASP.NET MVC with C#:
[HttpPost]
public ActionResult SetComment(int id, string comment)
{
// Yep, the browser can insert newlines as "\r\n" which overflows the allowed number of characters!
comment = comment.Replace("\r", "");
// More code...
}
I extend Robin Ridderholt solution, now we can refer maxlen to the validator
$.validator.addMethod('extMaxLength', function (value, element, maxlen){
if (maxlen > 0) {
var remaining = (maxlen - (parseInt($(element).val().replace(/(\r\n|\n|\r)/gm, '\n').length, 10)));
if (remaining < 0) {
return false;
}
}
return true;
});
I'd suggest just an improvement of Jakub Berezanski's solution.
I personally find his idea (of handling this generally on the server side) very good.
Just one problem with his sample code might be that the model is eventually already invalid at the time of overriding the BindProperty
method - if it's caused by just that field's length that we're correcting there.
Therefore, my improvement suggestion to his solution is to apply the same logic already in the GetPropertyValue
override, - which executes before the validation:
public class NewlinesNormalizingModelBinder : DefaultModelBinder
{
protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
{
// Note: if desired, one could restrict the conversion to properties decorated with [StringLength]:
// && propertyDescriptor.Attributes.OfType<StringLengthAttribute>().Any()
if (propertyDescriptor.PropertyType == typeof(string))
{
string originalString = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;
if (!string.IsNullOrEmpty(originalString)) return originalString.Replace("\r\n", "\n");
}
return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
}
}
I came accross the same kind of issue. this is due to the fact that in javascript, field.length would return the number of characters, but one character can use 2bytes to store information.
My problem was that a VARCHAR2 field in the DB can only store 4000Bytes of Information, or 2000Characters. We get easily confused and think we can store 4000 Characters in this kind of fields.
I think in your case, the field is not limited to 1000chars, but 1000bytes, which happend to be the same only of you use "standard characters" that use one byte of information, so I would rease the limit to 2000Bytes and keep the javascript validation to 1000chars. Then, of course I would go against the previous answer and do a server side validation on the number of characters.
Of course you have other solutions, in my case for instance (I wasn't using Jquery though), I tweaked the character counter to count twice every special character(this problems affect newline chars, but also accents ....)
Drop the server Validation and keep only Client-side Validation. In html new line = 3 char In database new line = 1 char So u have to keep only one at time. or Change the db char setting
精彩评论