【问题标题】:How do I use MVC Validation to display a warning message without making the field required?如何使用 MVC 验证来显示警告消息而不使该字段成为必填项?
【发布时间】:2015-03-27 13:33:10
【问题描述】:

我有一个 asp.net MVC 网站,用户在其中输入社会安全号码 (SSN)。如果 SSN 已被使用,客户端希望显示警告消息,但不想强制他们更改 SSN(在某些情况下,多条记录可以具有相同的 SSN)。

我继承的 MVC 代码有一个验证来检查 SSN 是否已被使用。代码效果很好。如果用户输入已使用的 SSN,则会出现一条消息,提示“SSN 已存在”并阻止提交表单。如何更改此设置以显示消息,但不会阻止提交表单?

ModelApplication.cs

    [StringLength(9, MinimumLength = 9, ErrorMessage = "Please Enter 9 Digit SSN No")]
    [Remote("IsSSNExist", "Admin", HttpMethod = "GET")]
    public string ApplicantSSN { get; set; }

AdminController.cs

    [HttpGet]
    public JsonResult IsSSNExist(string ApplicantSSN)
    {
        if (Session["viewapp"] == null)
        {
            if (obj_BllApp.IsSSNExist(ApplicantSSN))
                return Json("SSN already exists.", JsonRequestBehavior.AllowGet);
            else
                return Json(true, JsonRequestBehavior.AllowGet);
        }
        else
        {
            return Json(true, JsonRequestBehavior.AllowGet);
        }
    }

Application.cshtml

<label>
SSN
</label>
@Html.TextBoxFor(m => m.ApplicantSSN, new { @class = "input-small", @maxlength = "9", @onkeypress = "return ValidateNumberKeyPress(this, event);" })<br />
@Html.HiddenFor(m => m.ApplicantSSNID, new { id = "hdnApplicantSSN" })
span id="spAppSSn" class="SSNmsg">@Html.ValidationMessageFor(m => m.ApplicantSSN)</span>

更新

我也尝试使用响应标头,就像另一张海报建议的那样,但我无法让它工作。

这段代码没有返回任何东西并破坏了我拥有的其他javascript:

    $(function () {
    $("#txtApplicantSSN").change(function (xhr) {
        alert("Hello");
        var req = new XMLHttpRequest();
        req.open('GET', document.location, false);
        req.send(null);
        var headers = req.getResponseHeader("SSN-DUPLICATED").toLowerCase();
        alert(headers);
        alert("Goodbye");
    });
});

使用相同的概念,我尝试了另一种获取请求标头的方法,但我从未得到值。看起来设置标头值的验证是在 javascript 之后调用的。

    $(function () {
    $("#txtApplicantSSN").change(function () {
        var req = new XMLHttpRequest();
        req.open('GET', document.location, false);
        req.send(null);
        var headers = req.getResponseHeader('SSN-DUPLICATED');
        $("#remoteMessage").text(headers);
    });
});

我尝试使用会话变量进行类似的操作,但会话变量似乎是在 javascript 代码之后设置的。

    $(function () {
    $("#txtApplicantSSN").change(function () {
        var someSessionVariable = '@Request.RequestContext.HttpContext.Session["SSNExists"]';
        alert(someSessionVariable);
        $("#remoteMessage").text(someSessionVariable);
    });
});

我目前的想法是尝试在单击提交按钮时禁用验证,但我还没有找到方法。我试过这个

HtmlHelper.ClientValidationEnabled = false;

在控制器中,但它从不命中服务器端代码。我在到达控制器之前收到验证错误。

更新 #2

我使用取消类单击提交按钮时禁用了验证:

<input id="Submit1" type="submit" class="btn btn-primary cancel" value="Save" onclick="javascript: return ValidatonCoApplication();" />

这解决了该字段的问题,但禁用了所有其他字段的验证。有人可以在不关闭验证的情况下建议另一种方法来做我想做的事吗?

总之,这是带有 Razor 的 asp.net MVC。用户在文本框中输入 SSN 后,我需要在屏幕上显示一条消息,说明 SSN 是否有效。目前我在模型中有一个验证属性,但这不仅显示消息,还声明模型无效,因此不让用户进入下一页。我希望出现验证消息,但不希望模型无效。我很感激你能给我的任何帮助。谢谢。

【问题讨论】:

  • 如果存在 SSN 有效的条件,为什么不在 IsSSNExist() 方法中测试这些条件并返回 ether truefalse?如果条件取决于模型的其他属性,您可以使用RemoteAttributeAdditionalFields 属性传递这些属性的值。
  • SSN 总是有效的,但是客户端想要一条消息告诉用户它是否曾经被使用过。现在,验证显示消息(正确),但它说模型无效,因为验证属性([Remote("IsSSNExist", "Admin", HttpMethod = "GET")])。有没有办法在不阻止模型无效的情况下向视图返回消息“SSN 已存在”?
  • 在这种情况下,不要使用[Remote] 属性(用于验证)。相反,只需处理文本框的.change() 事件,将值传递给控制器​​方法,返回消息并使用消息更新 DOM
  • @StephenMuecke 感谢您的回复。我是 MVC 的新手。我不知道如何正确调用控制器方法并返回它的 javascript 函数。我在视图和控制器之间的所有交互都来自视图上的提交按钮,该按钮调用控制器中具有 [HttpPost] 属性的方法。如何将 .change() javascript 中的值传递给控制器​​,然后返回视图?

标签: json asp.net-mvc validation asp.net-mvc-4 requiredfieldvalidator


【解决方案1】:

由于您只想根据ApplicantSSN 的值显示一条消息(而不是使模型无效),因此删除[Remote] 属性,而是处理文本框的.change() 事件以调用控制方法和返回适当的消息。

控制器

public JsonResult IsSSNExist(string ApplicantSSN)
{
  bool isValid = // your logic
  if (isValid)
  {
    return Json(null, JsonRequestBehavior.AllowGet);
  }
  else
  {
    return Json(true, JsonRequestBehavior.AllowGet);
  }
}

查看

@Html.TextBoxFor(m => m.ApplicantSSN) // remove the onkeypress attribute
// add a placeholder for the message
<span class="field-validation-error"><span id="ssn-message">The SSN already exists.</span></span>

css

#ssn-message {
  display: none;
}

脚本

var url = '@Url.Action("IsSSNExist")';
var ssnMessage = $('#ssn-message');
$('#ApplicantSSN').change(function() {
  $.getJSON(url, { ApplicantSSN: $(this).val() }, function(response) {
    if(response) {
      ssnMessage.show();
    } else {
      ssnMessage.hide();
    }
  });
});

注意:如果用户输入了无效的值并且制表符超出了控制范围,则会显示该消息。如果用户随后再次开始在文本框中输入,您可能需要额外的逻辑来隐藏消息,在这种情况下,您还需要处理 keyup 事件

【讨论】:

  • 谢谢!那效果很好。现在我知道我可以使用 $.getJson 函数从 javascript 访问控制器。
【解决方案2】:

您可以将验证放在响应标头中,然后使用 jQuery 显示如下

[HttpGet]
public JsonResult IsSSNExist(string ApplicantSSN)
{
    if (Session["viewapp"] == null)
    {
        if (obj_BllApp.IsSSNExist(ApplicantSSN)){
            Response.AddHeader("SSN-DUPLICATED", "SSN already exists. ");
            return Json(true, JsonRequestBehavior.AllowGet);
        }
        else
            return Json(true, JsonRequestBehavior.AllowGet);
    }
    else
    {
        return Json(true, JsonRequestBehavior.AllowGet);
    }
}

并添加一个跨度来显示远程消息,并在您的视图中添加一些 jQuery,如下所示

<label>
     SSN
</label>
@Html.TextBoxFor(m => m.ApplicantSSN, 
      new { @class = "input-small",  @maxlength = "9", @onkeypress = "return ValidateNumberKeyPress(this, event);" })
<br />
@Html.HiddenFor(m => m.ApplicantSSNID, new { id = "hdnApplicantSSN" })

 <span id="spAppSSn" class="SSNmsg">
     @Html.ValidationMessageFor(m =>m.ApplicantSSN)</span>

 <span id="remoteMessage" class="SSNmsg">
      @Html.ValidationMessageFor(m =>m.ApplicantSSN)</span>


$(function () {
    $('#ApplicantSSNID').rules()
        .remote.complete = function (xhr) {
        var responseMessage=xhr.getResponseHeader('SSN-DUPLICATED');
        if (xhr.status == 200 && xhr.responseText === 'true') {
        jQuery('#remoteMessage')[0].innerHTML = 
              (responseMessage||'');
       }
    };
});

注意:请不要在 MVC 中使用 Session。这不是一个好习惯。

【讨论】:

  • 当你可以返回一个具有两个属性valid和message的json对象时,为什么要使用header?
  • @Bellash 感谢您的帮助。认为您的解决方案可能有效,但我可以让它做任何事情。我尝试了一个变体(见下文),但它只返回 null。验证似乎在 javascript 之后触发。任何想法如何解决这个问题? $(function () { $("#txtApplicantSSN").change(function () { var req = new XMLHttpRequest(); req.open('GET', document.location, false); req.send(null); var headers = req.getResponseHeader('SSN-DUPLICATED'); $("#remoteMessage").text(headers); }); });
  • @matt_lethargic 返回一个 json 对象听起来很有趣。你能告诉我怎么做吗?
  • 如果您返回 true,请将其替换为具有两个属性的类的实例,'Valid' 是一个布尔值,'Message' 是一个字符串
  • @matt_lethargic 你的意思是像 return Json(SOMECLASS, JsonRequestBehavior.AllowGet); ?然后我将如何从视图中访问该类?
【解决方案3】:

你不能真正按照你想要的方式做你想做的事。验证将通过或失败!您需要做的是删除 [Remote] 验证属性并检查您提交表单的操作。如果 SSN 存在,那么您必须在完成表单处理后传递此消息。

或者在SSN文本框失去焦点时使用javascript和Ajax检查SSN,然后在用户提交表单之前显示警告

【讨论】:

  • 如何使用 javascript 或 Ajax 来检查 SSN?我是 MVC 新手,不知道如何从 javascript 或 ajax 调用控制器中的 IsSSN 方法。你能告诉我怎么做吗?
猜你喜欢
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多