Я работаю над обнаружением исключений параллелизма.Я могу поймать исключения параллелизма, когда пользователь редактирует данные в порядке.У меня проблемы с перехватом исключения, когда пользователь удаляет данные.
На моей странице Index у меня есть кнопка для удаления каждого объекта Vehicle .Нажатие на эту кнопку приводит к Post к действию Delete.Вот действие Удалить:
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(VehicleIndexViewModel vehicleIndexViewModel)
{
try
{
Vehicle vehicle = db.Vehicles.Find(vehicleIndexViewModel.VehicleID);
//To test for concurrency errors
//vehicle.Timestamp = vehicleIndexViewModel.Timestamp;
db.Entry(vehicle).State = EntityState.Deleted;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DbUpdateConcurrencyException)
{
return RedirectToAction("Index",
new System.Web.Routing.RouteValueDictionary{{"concurrencyError", true }});
}
catch (DataException)
{
//Log the error (add a variable name after Exception)
ModelState.AddModelError(string.Empty, "The system was unable to delete that"
+ " vehicle. Try again, and if the problem persists"
+ " contact your system administrator.");
return RedirectToAction("Index");
}
}
Независимо от того, что пользователь должен быть перенаправлен на страницу указателя.Вот действие Get страницы индекса:
public ViewResult Index(bool? concurrencyError)
{
if (concurrencyError.GetValueOrDefault())
{
ViewBag.ConcurrencyErrorMessage = "The record you attempted to delete "
+ "was modified by another user after you got the original values. "
+ "The delete operation was canceled and the current values in the "
+ "database have been displayed. If you still want to delete this "
+ "record, click the Delete button again. Otherwise "
+ "click the Back to List hyperlink.";
}
IEnumerable<Vehicle> vehicles = db.Vehicles.Include(v => v.VehicleType);
IEnumerable<VehicleIndexViewModel> viewModel
= Mapper.Map<IEnumerable<Vehicle>,
IEnumerable<VehicleIndexViewModel>>(vehicles);
return View(viewModel);
}
Код никогда не перехватывает ошибку параллелизма.Я тестирую, открывая страницу индекса дважды.На одной из страниц я открываю страницу редактирования автомобиля и что-то меняю.После сохранения я возвращаюсь на другую страницу и нажимаю «Удалить». Действие Удалить запускается, и транспортное средство удаляется, но ошибка параллелизма не обнаруживается. Вы можете видеть, где я закомментировал vehicle.Timestamp = vehicleIndexViewModel.Timestamp ;.Я думал, что возвращение значения viewModel обратно в фактическое приведет к возникновению ошибки, но это тоже не сработает.
Я уверен, что есть что-то, чего я не понимаю, но что яделать неправильно?
EDIT
Эрик Филипс обнаружил логическую ошибку, которая у меня была, но была другая проблема, с которой я столкнулся сразу.Моя ViewModel не возвращала данные метки времени.Фактически, единственными данными, которые он возвращал, был VehicleID.
Когда я пытался добавить скрытое поле в форму, я получал ошибку.Код чуть ниже этого не будет работать:
<input type="hidden" name="Timestamp" value="@item"/>
Поле Timestamp должно быть допустимой строкой Base-64.Вы получите сообщение об ошибке:
Введенные данные не являются допустимой строкой Base-64, так как содержат не базовый 64-символ, более двух символов заполнения или не пробелсреди отступающих персонажей.
Вот так я и сохранил значение метки времени в представлении:
<input type="hidden" name="Timestamp" value="@Convert.ToBase64String(item.Timestamp)"/>
Итак, весь мой Html.BeginForm выглядит так:
@using (Html.BeginForm("Delete", "Vehicle", FormMethod.Post, null))
{
<input type="hidden" name="VehicleID" value="@item.VehicleID"/>
<input type="hidden" name="VehicleName" value="@item.VehicleName"/>
<input type="hidden" name="Timestamp" value="@Convert.ToBase64String(item.Timestamp)"/>
<input type="image" src="../../Content/Images/Delete.gif" value="Delete" name="deletevehicle @item.VehicleID" onclick="return confirm('Are you sure you want to delete @item.VehicleName.Replace("'", "").Replace("\"", "")?');"/>
}
Хотя мне действительно не нужно было помещать VehicleName в скрытое поле.
Как только это было сделано, все, что мне нужно было сделать, это использовать AutoMapper, чтобы отобразить значения обратно в объект транспортного средства, установить EntityStateУдалить и попробуйте сохранить изменения;
try
{
Vehicle vehicle = Mapper.Map<VehicleIndexViewModel, Vehicle>(vehicleIndexViewModel);
db.Entry(vehicle).State = EntityState.Deleted;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DbUpdateConcurrencyException)
{
return RedirectToAction("Index", new System.Web.Routing.RouteValueDictionary { { "concurrencyError", true } });
}
Вот и все!