我有一个senario,我必须在进行注册页面时检查数据库中是否存在用户名。为此我已经在我的模型中实现了远程属性的远程属性
[Remote("CheckUserNameAvaliable", "User", Httpmethod="Post")]
public string Username {get; set;}
我的方法看起来像这样
[HttpPost]
public JsonResult CheckUserNameAvaliable(string UserName)
{
SessionUser currentUser = this.sessionHelper.GetCurrentUser();
User user = this.userService.GetByUsername(UserName);
if (user != null && user.Id != currentUser.Id)
{
return Json(false);
}
return Json(true);
}
它适用于我,但问题是,每当我们在用户名Textbox上创建一个密钥时,它将提交此远程验证,但根据我的要求,我必须在用户名输入值后才启动此远程验证文本框。为此,我们可以强制添加延迟到远程验证属性?
有谁知道如何在MVC3中为远程验证添加延迟?
答案 0 :(得分:3)
MVC3在浏览器中使用jquery.validate插件。使用jquery.validate,字段验证直到第一次更改和字段模糊才开始,或者在未提交字段时提交。
对字段启动字段验证后,验证程序的onkeyup设置将控制是否对每个keyup事件执行验证。如果你在每个键按下的字段上执行远程验证,它可能会发送太多的ajax消息,同时强调客户端和服务器。
正如其他响应者所提到的,您可以通过设置validator.settings.onkeyup = false来抑制keyup验证,但这会抑制所有表单字段上的onkeyup验证,而不仅仅是那些具有远程验证规则的字段。我建议您在具有远程验证的字段具有焦点时抑制键入,然后在模糊字段时将其重新打开。
抑制onkeyup很容易。问题是将设置从false更改为true不会重新打开该功能。要重新打开它,您需要将其设置为$ .validator对象的默认值中定义的函数。
如果您正在使用MVC不显眼的验证,那么这是您的网页上包含的JavaScript代码。它将涵盖您网页上的所有表单。并确保使用jquery.validate版本1.9.0或更高版本'因为早期版本无法与IE 7或8一起正常工作(是的,我也必须支持这些用户):
$("form input[data-val-remote-url]").on({
focus: function () {
$(this).closest('form').validate().settings.onkeyup = false;
},
blur: function () {
$(this).closest('form').validate().settings.onkeyup =
$.validator.defaults.onkeyup;
}
});
答案 1 :(得分:2)
在使用MVC3和远程验证之前,我遇到过类似的问题。猜猜你希望事件在模糊时触发但不确定你如何告诉远程验证......
希望这会有所帮助
答案 2 :(得分:0)
如果你不想在密钥上验证但是在模糊上,则this就是你想要的
答案 3 :(得分:0)
没有一种方法是合适的答案,因为它消除了在错误已显示时重新验证 keyup 的能力。我仍然想要一个去抖动,而不是在每个键上点击 API 的当前实现。
我的解决方案是覆盖远程方法。
// Will use a simple variable to hold our current remote API request
// may want to do something smarter later
var holderForCurrentRemoteCall = null;
// keep the original as we're going to make use of it
jQuery.validator.methods._remoteRule = jQuery.validator.methods.remote;
jQuery.validator.methods.remote = function (value, element, param, method) {
// the orig remote method sets a pending class when the call is in progress
// we'll quickly exit and continue the pending.
if ($(element).hasClass('pending')) { return 'pending'; }
// we're going to need the previous value to stop any
// mid-stream request
method = typeof method === "string" && method || "remote";
var previous = this.previousValue(element, method);
if (holderForCurrentRemoteCall != null) {
// stop any current request
this.stopRequest(element, previous.valid);
// and clear out any timeout that hasn't executed yet
clearTimeout(holderForCurrentRemoteCall);
holderForCurrentRemoteCall = null;
}
// Within the orig remote call, it has some mnemonic so it won't
// make the same request twice
// as we can't capture it here, bubbling the request to orig would
// not give a desirable outcome for our stub.
// so I've taken the mnemonic part of the code and replicate here
if (this.optional(element)) {
return "dependency-mismatch";
}
if (!this.settings.messages[element.name]) {
this.settings.messages[element.name] = {};
}
previous.originalMessage = previous.originalMessage || this.settings.messages[element.name][method];
this.settings.messages[element.name][method] = previous.message;
param = typeof param === "string" && { url: param } || param;
var optionDataString = $.param($.extend({ data: value }, param.data));
if (previous.old === optionDataString) {
return previous.valid;
}
// End copy-pasta code
holderForCurrentRemoteCall = setTimeout(() => {
jQuery.validator.methods._remoteRule.call(this, value, element, param, method);
// remove the holder as we have nothing to cancel
holderForCurrentRemoteCall = null;
}, 300);
return "pending";
}