[英]How to avoid multiple submit of form in ASP.NET MVC?
我尝试使用ASP.NET MVC 5编写代码和脚本。是否使用模态来执行创建,更新和删除功能,该功能正常工作,但是在创建和更新中,因为我启用了远程验证,因此可以在首先但突然之间,当您再次单击提交按钮时,它将提交或发布数据。 简而言之,我的验证无效。 拜托,我需要帮助。
模型:
[Key]
[Display(Name = "ID")]
[Column("LAND_TYPE_CAT_ID", Order = 0, TypeName = "bigint")]
public long CategoryId { get; set; }
[Display(Name = "Category Name")]
[StringLength(100)]
[Column("LAND_TYPE_CAT", Order = 1, TypeName = "nvarchar")]
public string CategoryName { get; set; }
[Display(Name = "Description")]
[StringLength(255)]
[Column("LAND_TYPE_CAT_DESC", Order = 2, TypeName = "nvarchar")]
public string CategoryDescription { get; set; }
[Display(Name = "Created Date")]
[Column("CREATE_DATE", Order = 3, TypeName = "datetime")]
public DateTime? CreateDate { get; set; }
[Display(Name = "Modified Date")]
[Column("MODIFIED_DATE", Order = 4, TypeName = "datetime")]
public DateTime? ModifiedDate { get; set; }
[Display(Name = "Last Modified By")]
[StringLength(255)]
[Column("LAST_MODIFIED_BY", Order = 5, TypeName = "nvarchar")]
public string LastModifiedBy { get; set; }
ViewModels:用于创建:
[Display(Name = "Category Name")]
[Required(ErrorMessage = "This field is required.")]
[Remote("ValidateCreate", "Category", ErrorMessage = "This type already exists.")]
public string CategoryName { get; set; }
更新:
[Display(Name = "Category Name")]
[Required(ErrorMessage = "This field is required.")]
[Remote("ValidateEdit", "Category", AdditionalFields = "CategoryId, CategoryName",
ErrorMessage = "This type already exists.")]
public string CategoryName { get; set; }
控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(LandTypeCategoryCreateViewModels viewModel)
{
if (ModelState.IsValid)
{
var vm = new LandTypeCategory
{
CategoryName = viewModel.CategoryName,
CategoryDescription = viewModel.CategoryDescription,
CreateDate = DateTime.Now,
LastModifiedBy = "Tester"
};
_context.LandTypeCategories.Add(vm);
await _context.SaveChangesAsync();
TempData["Created"] = "New category type added.";
var url = Url.Action("Index", "Category", new {id = viewModel.CategoryId});
return Json(new {success = true, url});
}
return PartialView("_Create", viewModel);
}
public async Task<ActionResult> Edit(long? id)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var vm = await _context.LandTypeCategories.FindAsync(id);
if (vm == null)
return HttpNotFound();
var viewModel = new LandTypeCategoryEditViewModels
{
CategoryId = vm.CategoryId,
CategoryName = vm.CategoryName,
CategoryDescription = vm.CategoryDescription
};
return PartialView("_Edit", viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(LandTypeCategoryEditViewModels viewModel)
{
if (ModelState.IsValid)
{
var vm =
await _context.LandTypeCategories.SingleAsync(x => x.CategoryId == viewModel.CategoryId);
vm.CategoryName = viewModel.CategoryName;
vm.CategoryDescription = viewModel.CategoryDescription;
vm.ModifiedDate = DateTime.Now;
vm.LastModifiedBy = "Modify Tester";
_context.Entry(vm).State = EntityState.Modified;
await _context.SaveChangesAsync();
TempData["Updated"] = "Category type updated.";
var url = Url.Action("Index", "Category", new {id = viewModel.CategoryId});
return Json(new {success = true, url});
}
return PartialView("_Edit", viewModel);
}
远程验证:
public async Task<JsonResult> ValidateCreate(string CategoryName)
{
return
Json(
await _context.LandTypeCategories.AllAsync(
c => c.CategoryName.ToLower() != CategoryName.ToLower()), JsonRequestBehavior.AllowGet);
}
public async Task<JsonResult> ValidateEdit(int CategoryId, string CategoryName)
{
var category = await _context.LandTypeCategories.FindAsync(CategoryId);
var result = true;
if (category.CategoryName.ToLower() != CategoryName.ToLower())
result =
await _context.LandTypeCategories.AllAsync(
c => c.CategoryName.ToLower() != CategoryName.ToLower());
return Json(result, JsonRequestBehavior.AllowGet);
}
Index.cshtml
@model IEnumerable<MvcPPT.Models.LandTypeCategory>
@{
ViewBag.Title = "Category";
}
<div class="container">
<br />
<br />
<br />
@Html.ActionLink("Add New", "Create", "Category", new { ViewBag.CategoryId }, new { data_modal = "", @class = "btn btn-primary", style = "position: absolute;background-color: #3498db; border-color: #3498db;" })
<table class="table table-hover table-bordered" id="same-datatable" style="font-size: smaller; width: 100%;">
<thead>
<tr>
<th>@Html.DisplayNameFor(model => model.CategoryId)</th>
<th>@Html.DisplayNameFor(model => model.CategoryName)</th>
<th>@Html.DisplayNameFor(model => model.CategoryDescription)</th>
<th>@Html.DisplayNameFor(model => model.CreateDate)</th>
<th>@Html.DisplayNameFor(model => model.ModifiedDate)</th>
<th>@Html.DisplayNameFor(model => model.LastModifiedBy)</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.CategoryId)</td>
<td>@Html.DisplayFor(modelItem => item.CategoryName)</td>
<td>@Html.DisplayFor(modelItem => item.CategoryDescription)</td>
<td>@Html.DisplayFor(modelItem => item.CreateDate)</td>
<td>@Html.DisplayFor(modelItem => item.ModifiedDate)</td>
<td>@Html.DisplayFor(modelItem => item.LastModifiedBy)</td>
<td>
@Html.ActionLink("Edit", "Edit", "Category", new { id = item.CategoryId }, new { data_modal = "", @class = "btn btn-warning btn-xs" })
@Html.ActionLink("Delete", "Delete", "Category", new { id = item.CategoryId }, new { data_modal = "", @class = "btn btn-danger btn-xs" })
</td>
</tr>
}
</tbody>
</table>
</div>
<div id="myModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div id="myModalContent"></div>
</div>
</div>
</div>
_Create.cshtml
@model MvcPPT.ViewModels.LandTypeCategoryCreateViewModels
<div class="modal-header" style="background-color: #3498db; color: #fff;">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Add New Category Type</h4>
</div>
@using (Html.BeginForm())
{
<div class="modal-body">
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new {@class = "text-danger"})
<div class="form-group">
@Html.LabelFor(model => model.CategoryName, new {@class = "control-label col-md-4"})
<div class="col-md-8">
@Html.EditorFor(model => model.CategoryName, new {htmlAttributes = new {@class = "form-control"}})
@Html.ValidationMessageFor(model => model.CategoryName, "", new {@class = "text-danger"})
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CategoryDescription, new {@class = "control-label col-md-4"})
<div class="col-md-8">
@Html.EditorFor(model => model.CategoryDescription, new {htmlAttributes = new {@class = "form-control"}})
@Html.ValidationMessageFor(model => model.CategoryDescription, "", new {@class = "text-danger"})
</div>
</div>
<div class="modal-footer" style="padding-right: 0px;">
<input class="btn btn-success" type="submit" value="Save"/>
<button class="btn btn-default" type="button" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
}
@Scripts.Render("~/bundles/jqueryval")
_Edit.cshtml
@model MvcPPT.ViewModels.LandTypeCategoryCreateViewModels
<div class="modal-header" style="background-color: #3498db; color: #fff;">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Add New Category Type</h4>
</div>
@using (Html.BeginForm())
{
<div class="modal-body">
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new {@class = "text-danger"})
<div class="form-group">
@Html.LabelFor(model => model.CategoryName, new {@class = "control-label col-md-4"})
<div class="col-md-8">
@Html.EditorFor(model => model.CategoryName, new {htmlAttributes = new {@class = "form-control"}})
@Html.ValidationMessageFor(model => model.CategoryName, "", new {@class = "text-danger"})
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CategoryDescription, new {@class = "control-label col-md-4"})
<div class="col-md-8">
@Html.EditorFor(model => model.CategoryDescription, new {htmlAttributes = new {@class = "form-control"}})
@Html.ValidationMessageFor(model => model.CategoryDescription, "", new {@class = "text-danger"})
</div>
</div>
<div class="modal-footer" style="padding-right: 0px;">
<input class="btn btn-success" type="submit" value="Save"/>
<button class="btn btn-default" type="button" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
}
@Scripts.Render("~/bundles/jqueryval")
jQuery方式调用:
// Add new
$.ajaxSetup({ cache: false });
$("a[data-modal]").on("click",
function (e) {
$("#myModalContent").load(this.href,
function () {
$("#myModal").modal({
keyboard: true
},
"show");
bindForm(this);
});
return false;
});
function bindForm(dialog) {
$("form", dialog).submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result.success) {
$("#myModal").modal("hide");
window.location.reload();
} else {
$("#myModalContent").html(result);
bindForm(dialog);
}
}
});
return false;
});
}
由于创建和编辑表单都是局部视图,我猜这将在同一主视图上呈现,因此我建议您删除
@Scripts.Render("~/bundles/jqueryval")
从两个部分页面开始,并在主页顶部添加该行,因为当您单击创建按钮时,它将加载脚本包;再次单击您的编辑时,它将第二次加载脚本包
接下来是正确编写@ gtml.begin表单标签,例如
@using (Html.BeginForm(ActionName , ControllerName, FormMethod.Post))
我不确定您的表格发布方式现在如何运作
选项1:
您可以在按钮提交后将其禁用。
$('form').submit(function() {
$(this).find(':submit').attr('disabled', 'disabled');
});
选项2:
通过创建动作过滤器。 (因此,您可以在此处验证防伪令牌的重复。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.