Я вижу несколько проблем с вашим кодом.
Прежде всего, в вашем коде представления вы визуализируете строки таблицы внутри цикла.Внутри строк таблицы вы используете вспомогательный метод CheckBoxFor
для визуализации и привязки флажка из значения свойства Attended
.Но вы используете перегрузку, когда вы передаете анонимный объект в качестве атрибутов html, и там вы передаете значение атрибута Id
как checkboxID
.Это означает, что checkboxID
будет отображаться как Id
для всех флажков.Значения идентификатора должны быть уникальными.Если у вас есть одно и то же значение Id для более чем одного элемента, это недопустимый HTML.Это также приведет к тому, что ваше событие нажатия jQuery будет работать только для первого элемента из коллекции (флажок отображается в первой строке таблицы).
Давайте сначала исправим это.Вы можете использовать другой атрибут для подключения обработчика событий нажатия jQuery.Например, здесь я добавляю атрибут с именем ajaxupdate
вместо Id
@Html.CheckBoxFor(modelItem => item.Attended,
new { ajaxupdate="true",
@cID = item.Id, @eID = Model.Id })
С этим изменением будет отображаться 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 Внутренняя ошибка сервера, потому что вы получаете некоторую ошибку нулевой ссылки, потому что параметры вашего метода действия неправильно связаны с ожидаемыми значениями, а ваш запрос LINQ может возвращать вам нулевой объект, и вы пытаетесь обновить Attended
значение свойства этого объекта без предварительной проверки, является ли он объектом NULL или нет.
Давайте сначала исправим код на стороне клиента.Внутри обработчика события щелчка флажка выражение this
представляет элемент флажка, который был нажат.В своем коде бритвы вы устанавливаете значения cID
и eID
в качестве атрибутов элемента.Так что вы должны читать те, у кого есть метод attr
.Также вам не нужно отправлять строковую версию 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 со свойством status и message обратно клиенту.В случае использования исключения я отправляю версию исключения ToString()
в свойстве сообщения.Это следует делать только в том случае, если вы хотите увидеть это на стороне клиента (в основном во время разработки).Когда вы отправляете его в производство, вы не хотите передавать эту информацию клиенту.Вместо этого зарегистрируйте его.
Внутри обработчика success
вызова ajax вы можете при необходимости проверить свойство status
или message
.
success: function(result) {
alert(result.message);
},