视图组件在第二次提交时没有 detecting/returning Ajax 请求
View Component not detecting/returning Ajax request on 2nd submit
我有一个非常奇怪的问题,我的 ajax post 请求在页面加载后第一次工作正常,但如果我再次提交我的表单而不刷新页面,那么内容返回到整个页面,而不是仅仅更新 DIV。我花了好几天时间来寻找答案并通过反复试验,我怀疑这个问题与 Request.Headers["X-Requested-With"]
在第二次提交时为空有关。请注意,我正在向 ajax 请求返回一个视图组件,并且我的 ajax 代码位于单独的 js 文件中。
视图组件(这包含在 ajax 请求 returns 时提交和替换的表单。它在页面加载或刷新后正常工作)
@model MSIC.Models.ClientViewModels.VisitMovementViewModel
@{
bool inProgress = (bool)ViewData["inProgress"];
}
<form asp-controller="Client" asp-action="VisitMovement" asp-route-id="@Model.VisitMovementID" id="formVisitAction" method="post" onsubmit="AjaxSubmit(this)">
<input asp-for="VisitID" type="hidden" />
<input asp-for="StageNo" type="hidden" />
<input type="hidden" id="replaceID" name="replaceID" value="#ClientVisit" />
<input type="hidden" id="submitAction" name="submitAction" />
<div class="col-md-9 no-padding">
<input type="text" id="visitMovementComment" name="visitMovementComment" class="form-control" placeholder="Comment..." required>
</div>
<div class="input-group col-md-3">
<input type="text" id="visitMovementBoothNo" name="visitMovementBoothNo" class="form-control" placeholder="Booth..." required>
<div class="input-group-btn">
<button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" @((inProgress) ? "" : "disabled")>Action <span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right">
@if (Model.Buttons != null)
{
foreach (var item in Model.Buttons)
{
if (item.beforeDivider)
{
<li><button type="@item.Type" name="@item.Name" class="btn btn-link btn-block btn-flat" value="@item.Value" onclick="@item.OnClick">@item.Text</button></li>
}
}
<li role="separator" class="divider"></li>
foreach (var item in Model.Buttons)
{
if (!item.beforeDivider)
{
<li><button type="@item.Type" name="@item.Name" class="btn btn-link btn-block btn-flat" value="@item.Value" onclick="@item.OnClick">@item.Text</button></li>
}
}
}
</ul>
</div>
</div>
</form>
Ajax 请求位于单独的 JS 文件中(调试时一切都按预期第一次运行但是在返回视图组件并第二次提交表单后成功,错误,完整的函数永远不会触发,并且返回的数据加载到整个页面)
function AjaxSubmit(form) {
$form = $(form);
var replaceID = $('input#replaceID', $form).val();
var formData = $form.serialize();
if (!$form[0].checkValidity()) {
return false;
}
$form.submit(function (e) {
e.preventDefault();
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: formData,
async: true,
processData: false,
cache: false,
success: function (data) {
$(replaceID).html(data);
},
error: function (xhr, status, error) {
console.log(xhr.status + " - " + error);
},
complete: function (data) {
console.log(data);
}
});
});
}
Action Method(我怀疑这个问题可能与 Request.Headers["X-Requested-With"]
在第二次提交时为空有关,因此 MVC 没有意识到这是一个 ajax 请求,因此 returns 结果到页面而不是返回到 ajax 请求)
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> VisitMovement(int id, int submitAction, int? visitMovementBoothNo, string visitMovementComment, VisitMovementViewModel model)
{
var test1 = Request.ContentType; //1ST REQUEST = "application/x-www-form-urlencoded; charset=UTF-8", 2ND REQUEST = "application/x-www-form-urlencoded"
var test2 = Request.Headers["X-Requested-With"]; //1ST REQUEST = "XMLHttpRequest", 2ND REQUEST = Empty
try
{
if (ModelState.IsValid)
{
bool complete = false;
switch (submitAction)
{
case 2: //Proceed to Stage 2
model.StageNo = 2;
break;
case 3: //Proceed to Stage 3
model.StageNo = 3;
break;
case 4: //Complete Visit
complete = true;
break;
default:
return BadRequest("Could not determine action.");
}
await visitAPI.VisitMovement(id, model.VisitID, submitAction, model.StageNo, visitMovementBoothNo, visitMovementComment, complete);
return ViewComponent("ClientVisit", new { visitID = model.VisitID });
}
else
{
return BadRequest(ModelState);
}
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
如果我的假设是正确的,为什么 ajax 请求在第二次提交时没有发送正确的 headers,我该如何解决?如果不是,还有什么问题?
我认为问题是当 data/view 组件返回时表单提交事件丢失了。我通过将 ajax post 更改为以下解决了问题...
$(document).on('submit', 'form.ajax-form', function (e) {
var replaceID = $('input#replaceID', $(this)).val();
var replaceType = $('input#replaceType', $(this)).val();
e.preventDefault();
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
data: $(this).serialize(),
async: true,
processData: false,
cache: false,
success: function (data) {
$(replaceID).html(data);
},
error: function (xhr, status, error) {
AjaxOnFailure(xhr, status, error);
}
});
});
我有一个非常奇怪的问题,我的 ajax post 请求在页面加载后第一次工作正常,但如果我再次提交我的表单而不刷新页面,那么内容返回到整个页面,而不是仅仅更新 DIV。我花了好几天时间来寻找答案并通过反复试验,我怀疑这个问题与 Request.Headers["X-Requested-With"]
在第二次提交时为空有关。请注意,我正在向 ajax 请求返回一个视图组件,并且我的 ajax 代码位于单独的 js 文件中。
视图组件(这包含在 ajax 请求 returns 时提交和替换的表单。它在页面加载或刷新后正常工作)
@model MSIC.Models.ClientViewModels.VisitMovementViewModel
@{
bool inProgress = (bool)ViewData["inProgress"];
}
<form asp-controller="Client" asp-action="VisitMovement" asp-route-id="@Model.VisitMovementID" id="formVisitAction" method="post" onsubmit="AjaxSubmit(this)">
<input asp-for="VisitID" type="hidden" />
<input asp-for="StageNo" type="hidden" />
<input type="hidden" id="replaceID" name="replaceID" value="#ClientVisit" />
<input type="hidden" id="submitAction" name="submitAction" />
<div class="col-md-9 no-padding">
<input type="text" id="visitMovementComment" name="visitMovementComment" class="form-control" placeholder="Comment..." required>
</div>
<div class="input-group col-md-3">
<input type="text" id="visitMovementBoothNo" name="visitMovementBoothNo" class="form-control" placeholder="Booth..." required>
<div class="input-group-btn">
<button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" @((inProgress) ? "" : "disabled")>Action <span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right">
@if (Model.Buttons != null)
{
foreach (var item in Model.Buttons)
{
if (item.beforeDivider)
{
<li><button type="@item.Type" name="@item.Name" class="btn btn-link btn-block btn-flat" value="@item.Value" onclick="@item.OnClick">@item.Text</button></li>
}
}
<li role="separator" class="divider"></li>
foreach (var item in Model.Buttons)
{
if (!item.beforeDivider)
{
<li><button type="@item.Type" name="@item.Name" class="btn btn-link btn-block btn-flat" value="@item.Value" onclick="@item.OnClick">@item.Text</button></li>
}
}
}
</ul>
</div>
</div>
</form>
Ajax 请求位于单独的 JS 文件中(调试时一切都按预期第一次运行但是在返回视图组件并第二次提交表单后成功,错误,完整的函数永远不会触发,并且返回的数据加载到整个页面)
function AjaxSubmit(form) {
$form = $(form);
var replaceID = $('input#replaceID', $form).val();
var formData = $form.serialize();
if (!$form[0].checkValidity()) {
return false;
}
$form.submit(function (e) {
e.preventDefault();
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: formData,
async: true,
processData: false,
cache: false,
success: function (data) {
$(replaceID).html(data);
},
error: function (xhr, status, error) {
console.log(xhr.status + " - " + error);
},
complete: function (data) {
console.log(data);
}
});
});
}
Action Method(我怀疑这个问题可能与 Request.Headers["X-Requested-With"]
在第二次提交时为空有关,因此 MVC 没有意识到这是一个 ajax 请求,因此 returns 结果到页面而不是返回到 ajax 请求)
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> VisitMovement(int id, int submitAction, int? visitMovementBoothNo, string visitMovementComment, VisitMovementViewModel model)
{
var test1 = Request.ContentType; //1ST REQUEST = "application/x-www-form-urlencoded; charset=UTF-8", 2ND REQUEST = "application/x-www-form-urlencoded"
var test2 = Request.Headers["X-Requested-With"]; //1ST REQUEST = "XMLHttpRequest", 2ND REQUEST = Empty
try
{
if (ModelState.IsValid)
{
bool complete = false;
switch (submitAction)
{
case 2: //Proceed to Stage 2
model.StageNo = 2;
break;
case 3: //Proceed to Stage 3
model.StageNo = 3;
break;
case 4: //Complete Visit
complete = true;
break;
default:
return BadRequest("Could not determine action.");
}
await visitAPI.VisitMovement(id, model.VisitID, submitAction, model.StageNo, visitMovementBoothNo, visitMovementComment, complete);
return ViewComponent("ClientVisit", new { visitID = model.VisitID });
}
else
{
return BadRequest(ModelState);
}
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
如果我的假设是正确的,为什么 ajax 请求在第二次提交时没有发送正确的 headers,我该如何解决?如果不是,还有什么问题?
我认为问题是当 data/view 组件返回时表单提交事件丢失了。我通过将 ajax post 更改为以下解决了问题...
$(document).on('submit', 'form.ajax-form', function (e) {
var replaceID = $('input#replaceID', $(this)).val();
var replaceType = $('input#replaceType', $(this)).val();
e.preventDefault();
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
data: $(this).serialize(),
async: true,
processData: false,
cache: false,
success: function (data) {
$(replaceID).html(data);
},
error: function (xhr, status, error) {
AjaxOnFailure(xhr, status, error);
}
});
});