我有一个MVC应用程序,它是一个非常简单的6个字段。表单数据通过Entity Framework保存到我的数据库中。大多数情况下,数据可以正常保存而不会出现问题,但会出现随机重复数据。我首先认为这是一个EF问题,重复项(有时是同一记录的1,3,5)被保存,时间戳不到一秒,将它们分开。但我运行了一个单元测试并取出了控制器操作中的所有相同逻辑来保存数据,我的数据永远不会重复。我有JQuery禁用提交按钮,所以我知道它与多次点击无关。
所以我的问题是:我的控制器POST动作是否可能通过一些未知行为被多次调用?当我在保存数据的控制器操作中设置断点时,我无法在VS中复制问题。我也发现很难复制,而且完全是随机的。有没有人遇到这个或有任何建议?它出现在所有浏览器(FF,IE,Chrome)中。感谢
我通过提琴手运行我的应用程序,有时当我提交表单时,我会在单击一下按钮时看到2个POST请求。
代码
@model PersonViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(false, "The following errors have occurred:", new { @class = "alert alert-danger", @role = "alert" })
<hr />
<p>Please enter your personal details below. (* denotes required field)</p>
<div class="form-group">
@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control", @maxlength = "50", @title = "Legal First Name" } })
@Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.MiddleName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.MiddleName, new { htmlAttributes = new { @class = "form-control", @maxlength = "50", @placeholder = "enter 'None' if none", @title = "Legal Middle Name" } })
@Html.ValidationMessageFor(model => model.MiddleName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control", @maxlength = "50", @title = "Legal Last Name" } })
@Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group" id="EmailGroup">
@Html.LabelFor(model => model.EmailAddress, htmlAttributes: new { @class = "control-label col-md-2", @id = "EmailLabel" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmailAddress, new { htmlAttributes = new { @class = "form-control", @maxlength = "100", @title = "Email Address" } })
@Html.ValidationMessageFor(model => model.EmailAddress, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-2"></div>
<div class="col-md-8">
<input type="submit" value="Submit" id="affSubmit" class="btn btn-primary btn-md" />
</div>
</div>
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/Scripts/Custom.js")
}
Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-default">
</div>
<div class="container body-content">
@RenderBody()
<hr />
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/jquery-ui")
@RenderSection("scripts", required: false)
Custom.js
$().ready(function () {
$('form').submit(function (e) {
if ($('form').valid()) { //make sure form is valid
$('#affSubmit').prop('disabled', true);
$('#affSubmit').val("Please wait...");
this.submit();
}
}
});
ControllerAction
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(PersonModel model)
{
try
{
if (ModelState.IsValid)
{
PersonBLL bll = new PersonBLL();
PersonModel result = bll.SavePerson(model);
if (result.PersonID > 0)
{
return View("CreateSuccess");
}
else
{
ModelState.AddModelError("SaveError", "An error occurred while attempting to save, please try again later.");
}
}
}
catch (Exception ex) //unexpected error so log it, and redisplay form
{
Common.HandleException(ex);
ModelState.AddModelError("SaveError", "An error occurred while attempting to save, please try again later.");
}
//if we get here reshow page
return View(model);
}
答案 0 :(得分:0)
使用jQuery提交时使用preventDefault 将其添加到您的cutsom.js文件
$().ready(function () {
// not here
$('form').submit(function (e) {
e.preventDefault();// but here
// the rest of your code here
}
}
首先我编辑了我的答案,e.preventDefault进入了提交事件处理程序。当您点击提交按钮时,将提交表单的默认行为,这就是为什么您的表单由于默认行为而被提交两次的原因,第二次提交您的代码this.submit(); e.preventDefault取消了提交事件的默认行为,因此只能使用您的代码提交表单。