[英]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.