9

私のasp.net mvcアプリケーションでこの問題が発生しました。

私のモデルの1つに「説明」フィールドがあります。このフィールドのデータベース列は に設定されていNVarchar(300)ます。

私の見解では、次のようにテキストエリアを作成しています。

@Html.TextAreaFor(m => m.Description, new { maxlength = "300" })

クライアント側の検証に「jquery.validate.unobtrusive.min.js」を使用しています。そのため、ユーザーがテキストエリアに入力し、コンテンツの長さが 300 文字を超えると、「300 文字以下で入力してください」というメッセージが表示されます。

次のシナリオが来るまで、すべてがうまくいきます。ユーザーは、テキスト領域に次のデータを入力します。

f
f
f
f
f
f
f
f
sdfa

(このコンテンツには 8 行の改行があります)

「目立たない」検証によると、このコンテンツの長さは 300 (改行「\n」を 1 文字としてカウント)であるため、検証に合格し、ページがポストバックされます。

私のC#コードでは、エンコーディングにより、同じコンテンツが長さ308になり(新しい行「\r\n」を2文字としてカウント)、300文字しか許可されないため、データベース操作に失敗します。

この特定のプロパティに属性が必要だと誰かが言っている場合、StringLength属性を持たないのには次の理由があります。

この属性を配置すると、この特定のプロパティに対してクライアント側の検証が行われず、サーバーに送られ、モデルが有効でないため、エラー メッセージが表示されたページに戻ります。

これに対する可能な解決策を教えてください。

4

2 に答える 2

7

@Chris による解決策を詳しく調べたところ、@maxlength属性を持つ textarea 以外のコントロールで無限ループが発生することがわかりました。
さらに、value(=バリデーターに渡された textarea の値) を使用すると、先頭と末尾の改行が既に切り取られていることがわかりました。これは、これらの改行を含むテキストを保存しようとしたときに、データベース操作がまだ失敗していることを意味します。
だからここに私の解決策があります:

(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);

Chrome といくつかの IE バージョンでこれをテストしたところ、問題なく動作しました。

于 2013-03-14T05:01:20.730 に答える
4

jquery.validate.js をインクルードした後、javascript に以下を追加することで、クライアント検証での getLength の動作をダブル カウント改行に変更できます。これにより、サーバー側とクライアント側の長さの方法が一致し、StringLength 属性を使用できるようになります (StringLength に関する問題は、サーバーとクライアントの検証方法が異なることだと思います)。

$.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);
};
于 2012-07-09T13:32:56.883 に答える