【发布时间】:2020-01-06 12:36:19
【问题描述】:
将formvalidation.io 库与Ajax.BeginForm 一起使用时,[HttpPost] 方法会被调用两次。
我可以确认我没有多次引用 jquery.unobtrusive-ajax.js,因为这是一个常见错误,我也没有在我的 BundleConfig 中使用通配符来引用 jquery.unobtrusive-ajax.js,我相信这也会引入同样的问题。
我还使用PartialViewResult 而不是ActionResult 来确保我不会通过_Layout.cshtml 重新包含jquery.unobtrusive-ajax.js
从广泛的测试中,我发现删除初始化表单验证的代码可以消除双重发布问题。原因是初始化时 formvalidation 会将novalidate="novalidate" 添加到表单中。
我想保留表单验证功能,以防止在没有输入正确数据的情况下发布表单,同时也防止不必要的额外 HttpPost 调用。
请看我下面的代码来演示这个问题:
RouteConfig.cs
routeCollection.MapRoute("Test", "Home/Test/{id}/{form}", new { controller = "Home", action = "Test", id = UrlParameter.Optional, form = UrlParameter.Optional });
BundleConfig.cs
bundleCollection.Add(new ScriptBundle("~/scriptBundle/_test").Include("~/Scripts/_test.js"));
Test.cs
public class Test
{
public int Id { get; set; }
//[Required]
public string Description { get; set; }
}
HomeController.cs
public PartialViewResult Test(int id, bool form)
{
var test = new WebApplication1.Models.Test
{
Id = id,
Description = "Blah"
};
return PartialView(!form ? "_Test" : "_TestForm", test);
}
[HttpPost]
public PartialViewResult Test(WebApplication1.Models.Test model)
{
return PartialView(!ModelState.IsValid ? "_TestForm" : "_Test", model);
}
Index.cshtml
<div class="row">
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">Test</div>
<div class="panel-body" id="TestBody">
<table class="table table-bordered no-margin-bottom">
<tr>
<td>@Model.Id</td>
</tr>
<tr>
<td>@Model.Description</td>
</tr>
<tr>
<td colspan="4">@Ajax.ActionLink("Edit Test", "Test", "Home", new { id = Model.Id, form = true }, new AjaxOptions { UpdateTargetId = "TestBody" }, new { title = "Click to Edit Test" })</td>
</tr>
</table>
</div>
</div>
</div>
</div>
_TestForm.cshtml
@using WebApplication1.Helpers
@model WebApplication1.Models.Test
@{
Layout = null;
}
@using (Ajax.BeginForm("Test", "Home", null, new AjaxOptions { UpdateTargetId = "TestBody" }, new { @class = "form-horizontal", Id = "TestForm" }))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.Id)
<fieldset>
<div class="col-sm-12">
<div class="input-group">
<span class="input-group-addon">Description</span>
@Html.TextBoxForExt(model => model.Description)
<p class="help-block">@Html.ValidationMessageFor(model => model.Description)</p>
</div>
</div>
<div class="form-group" style="margin-bottom: -15px">
<div class="col-sm-12">
<div style="float: left">
<button type="submit" name="submitButton" class="btn btn-primary" title="Click to Update">Update</button>
</div>
<div style="float: right">
@Ajax.ActionLink("Cancel", "Test", "Home", new { Model.Id, form = false }, new AjaxOptions { UpdateTargetId = "TestBody" }, new { @class = "btn btn-primary", title = "Click to Cancel" })
</div>
</div>
</div>
</fieldset>
}
@Scripts.Render("~/scriptBundle/_test")
_test.js
$(document).ready(function() {
$("#TestForm").formValidation({
framework: "bootstrap",
fields: {
'Description': {
validators: {
callback: {
callback: function(value) {
debugger;
var id = parseInt($("#Id").val(), 0) || 0;
if (value === "" && id === 0) {
return {
valid: false,
message: "Please enter a Description"
};
}
return true;
}
}
}
}
}
});
});
_Test.cshtml
@model WebApplication1.Models.Test
<table class="table table-bordered no-margin-bottom">
<tr>
<td>@Model.Id</td>
</tr>
<tr>
<td>@Model.Description</td>
</tr>
<tr>
<td colspan="4">@Ajax.ActionLink("Edit Test", "Test", "Home", new { id = Model.Id, form = true }, new AjaxOptions { UpdateTargetId = "TestBody" }, new { title = "Click to Edit Test" })</td>
</tr>
</table>
【问题讨论】:
标签: c# jquery ajax.beginform formvalidation.io