单击复选框时,我试图使用Ajax发布到控制器。它应该更新现有对象。我的两个问题是:
希望有人可以帮忙
$('#checkboxID').on('click', function () {
$.ajax({
url: '@Url.Action("Attending", "GuestBookings")',
type: 'POST',
data: JSON.stringify({
"cID": $(this).val('cID'), "eID": $(this).val('eID'), "check": $(this).is(':checked') ? 1 : 0
}),
success: function(result) {
alert("Succeeded post");
},
error: function(result) {
alert("Failed to post");
}
});
});
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Attending(string cID, string eID, string check)
{
if (ModelState.IsValid)
{
var guest = await _context.Guests
.Where(g => g.CustomerId.ToString() == cID && g.EventId.ToString() == eID).FirstOrDefaultAsync();
if (check == "0")
{
guest.Attended = false;
}
else
{
guest.Attended = true;
}
try
{
_context.Update(guest);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
}
}
return Json(true);
}
<tbody>
@foreach (var item in Model.GuestsBooked)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Surname)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.CheckBoxFor(modelItem => item.Attended, new { @id = "checkboxID", @cID = item.Id, @eID = Model.Id })
</td>
<td>
@Html.ActionLink("Details", "Details", "Customers", new { id = item.Id }) |
@Html.ActionLink("Unbook", "Delete", "GuestBookings", new { id = item.Id, eventId = Model.Id }) |
</td>
</tr>
}
</tbody>
我发现您的代码存在一些问题。
首先,在您的视图代码中,您正在循环内渲染表行。在表行中,您正在使用CheckBoxFor
helper方法来呈现并绑定Attended
属性值中的复选框。但是,您正在使用重载,其中您要将匿名对象作为html属性传递,并且在那里将Id
属性值传递为checkboxID
。这意味着它会呈现checkboxID
为Id
所有的复选框。ID值应唯一。如果您对多个元素使用相同的ID值,则该HTML无效。这也将导致您的jQuery click事件仅适用于集合中的第一项(在第一行表中呈现的复选框)。
让我们先解决这个问题。您可以使用另一个属性来连接jQuery click事件处理程序。例如,在这里我要添加一个名为的属性,ajaxupdate
而不是Id
@Html.CheckBoxFor(modelItem => item.Attended,
new { ajaxupdate="true",
@cID = item.Id, @eID = Model.Id })
进行此更改后,它将像这样呈现checkbox元素的HTML标记(为便于阅读,省略了某些属性)。这里的重要部分是ajaxupdate
属性的存在。
<input ajaxupdate="true" checked="checked"
cid="1" eid="2" name="item.Active" type="checkbox" >
现在连接click
事件处理程序,我们可以使用此数据属性选择器。
$('[ajaxupdate="true"]').on('click', function () {
// to do : code for ajax call
});
修复此问题后,我们将发现click事件至少是在执行事件处理程序代码时执行的。但是您会注意到,ajax调用从服务器收到400错误的请求响应。发生这种情况是因为您的操作方法已用ValidateAntiForgeryToken
属性装饰。当用此方法装饰操作方法时,框架将检查提交的请求数据,如果未找到有效的防伪令牌,则将其视为错误请求,并将发送400响应。
要解决此问题,您可以显式读取__RequestVerificationToken
隐藏输入的值(由@Html.AntiForgeryToken()
视图中的方法调用生成),并将其发送到ajax请求标头中。
var t = $("input[name='__RequestVerificationToken']").val();
$.ajax({ url: '@Url.Action("Attending", "Home")',
type: 'POST',
headers:
{
"RequestVerificationToken": t
},
//existing code for ajax
})
另一种选择是删除ValidateAntiForgeryToken
。但是会影响安全性。”
现在,通过上述步骤,我们必须解决我们的400响应问题。现在您可能会收到500 Internal server error,这是因为您收到一些null引用错误,因为您的操作方法参数未正确与您期望的值绑定,并且LINQ查询可能返回了null对象,并且您尝试更新Attended
属性该对象的值,而无需先检查它是否为NULL对象。
让我们首先修复客户端代码。在复选框的click事件处理程序内,该this
表达式表示被单击的复选框元素。在您的剃刀代码中,您将cID
和eID
值设置为元素的属性。因此,您应该阅读有关attr
method的内容。另外,您不需要发送JSON字符串版本。只需将JavaScript对象作为data
属性传递即可。
因此,客户端代码的最终清理版本为
$(function () {
$('[ajaxupdate="true"]').on('click', function () {
var t = $("input[name='__RequestVerificationToken']").val();
var $this = $(this);
$.ajax({
url: '@Url.Action("Attending", "GuestBookings")',
type: 'POST',
headers:
{
"RequestVerificationToken": t
},
data: {
"cID": $this.attr('cID'),
"eID": $this.attr('eID'),
"check": $this.is(':checked') ? 1 : 0
},
success: function(result) {
alert("Succeeded post");
console.log(result);
},
error: function(xhr,status,errorThrown) {
alert("Failed to post");
console.log(errorThrown);
}
});
});
});
我的另一个建议是在服务器端代码上使用正确的类型。您将string
类型用作参数,然后ToString()
调用数字属性进行比较(与Where子句中的谓词比较)。而不是这样做,而是使用适当的数字类型作为参数。
public async Task<IActionResult> Attending(int cID, int eID, int check)
{
var guest = await _context.Guests
.Where(g => g.CustomerId == cID
&& g.EventId == eID)
.FirstOrDefaultAsync();
if(guest!=null)
{
guest.IsActive = check == 0;
try
{
_context.Update(guest);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
// Make sure to log the exception and not leak the ToString version to client.
return Json(new { status = false, message = ex.ToString() });
}
return Json(new { status = true, message = "Updated" });
}
return Json(new { status = false, message = "Customer not found!" });
}
在上面的代码中,我将具有状态和消息属性的JSON对象返回给客户端。对于异常用例,我将ToString()
在message属性中发送异常的版本。仅当您希望在客户端(主要是在开发过程中)看到它时,才应该这样做。当您将其运送到生产环境时,您不想将此信息泄漏给客户。而是记录它。
在success
ajax调用的处理程序内部,您可以根据需要检查status
或message
属性。
success: function(result) {
alert(result.message);
},
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句