У меня был метод EditEmployee в AdminController. Когда я отправляю форму редактирования, отображается ошибка 404. Кажется, метод не распознает EmployeeId, я привязываю, но не могу понять.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditEmployee(int id, [Bind("EmployeeId,Name,Email,Password,RoleId,ShopId")] Employee employee)
{
if (id != employee.EmployeeId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(employee);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!_context.Employees.Any(e => e.EmployeeId == employee.EmployeeId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
var errors = ModelState.Values.SelectMany(v => v.Errors);
foreach (var error in errors)
{
Console.WriteLine(error.ErrorMessage);
}
ViewBag.RoleId = new SelectList(_context.Roles, "RoleId", "RoleName", employee.RoleId);
ViewBag.ShopId = new SelectList(_context.RetailShops, "ShopId", "Address", employee.ShopId);
return View(employee);
}
и это мое мнение:
@model Nexus.Models.Employee
<div class = "row">
<div class = "col-md-4">
<form asp-action = "EditEmployee" asp-controller = "Admin" method = "post">
<div class = "text-danger"></div>
<div class = "form-group">
<label class = "control-label">Name</label>
<input asp-for = "Name" class = "form-control" />
<span class = "text-danger" asp-validation-for = "Name"></span>
</div>
<div class = "form-group">
<label class = "control-label">Email</label>
<input asp-for = "Email" class = "form-control" />
<span class = "text-danger" asp-validation-for = "Email"></span>
</div>
<div class = "form-group">
<label class = "control-label">Password</label>
<input asp-for = "Password" class = "form-control" />
<span class = "text-danger" asp-validation-for = "Password"></span>
</div>
<div class = "form-group">
<label class = "control-label">Role</label>
<select asp-for = "RoleId" class = "form-control" asp-items = "ViewBag.RoleId"></select>
<span class = "text-danger" asp-validation-for = "RoleId"></span>
</div>
<div class = "form-group">
<label class = "control-label">Shop address</label>
<select asp-for = "ShopId" class = "form-control" asp-items = "ViewBag.ShopId"></select>
<span class = "text-danger" asp-validation-for = "ShopId"></span>
</div>
<br />
<div class = "form-group">
<input type = "submit" value = "Submit" class = "btn btn-primary" />
</div>
</form>
</div>
Я также попробовал другой подход, используя IFormCollection, но он тоже не сработал:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditEmployee(int id, IFormCollection collection)
{
try
{
var employee = await _context.Employees.FirstOrDefaultAsync(m => m.EmployeeId == id);
if (employee == null)
{
return NotFound();
}
employee.EmployeeId = Convert.ToInt32(collection["EmployeeId"]);
employee.Name = collection["Name"];
employee.Email = collection["Email"];
employee.Password = collection["Password"];
employee.RoleId = Convert.ToInt32(collection["RoleId"]);
employee.ShopId = Convert.ToInt32(collection["ShopId"]);
_context.Update(employee);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateConcurrencyException)
{
if (!_context.Employees.Any(e => e.EmployeeId == id))
{
return NotFound();
}
else
{
throw;
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
return View();
}
}
В обоих случаях метод EditEmployee, похоже, не обновляет данные сотрудника правильно, и я не понимаю, почему. Символ ModelState недействителен, но я не могу определить, что его вызывает.
Может ли кто-нибудь помочь мне понять, что я делаю неправильно? Любые предложения или улучшения будут с благодарностью приняты. Я новичок в ASP.NET Core, большое спасибо.
В этой строке employee.EmployeeId = Convert.ToInt32(collection["EmployeeId"]); вам нужна эта строка, вы должны обновить другое свойство по идентификатору, а не сам идентификатор.
Кроме того, из-за того, что EmployeeId не включен в форму как скрытое поле. Без него значение «EmployeeId» не будет отправлено обратно на сервер, что приведет к несоответствию между параметром id и свойством «EmployeeId» объекта «Сотрудник». Это может вызвать ошибку 404, которую вы видите.
Вам нужно будет добавить эту строку <input type = "hidden" asp-for = "EmployeeId" /> в представление редактирования внутри элемента.
Большое вам спасибо, я добавил <input type = "hidden" asp-for = "EmployeeId" /> и изменил метод EditEmployee, чтобы он использовал IFormCollection и извлекал свойства сотрудника из коллекции. Это помогает обновлять другие свойства без редактирования идентификатора сотрудника.
Я также предоставил вам обновленный код, который вы можете протестировать. Убедитесь, что вы правильно заменили их в своем проекте.
Если вы хотите сделать что-то подобное, заставьте его выбрать идентификатор из маршрута, а затем передать модель, это намного проще. У вас действительно должен быть DTO (объект передачи данных) для обеспечения безопасности, чтобы вы не взаимодействовали напрямую с сущностями или людьми, которые потенциально могут играть. Но, игнорируя часть DTO, это должно сработать для вас. [HttpPost("{id:int}", Name = nameof(EditEmployee))] public async Task<IActionResult> EditEmployee([FromRoute] int id, [FromBody] Сотрудник сотрудникМодель)





В обоих случаях метод EditEmployee, похоже, не обновляет данные о сотруднике указаны правильно, и я не понимаю, почему. ModelState — это недействителен, но я не могу определить, что является причиной этого
Судя по вашему общему фрагменту кода, вы получаете 404, а ваша информация Employee не обновляется из-за отсутствия Employee.EmployeeId в вашей форме редактирования.
Потому что, когда вы публикуете редактирование формы вашего контроллера, ожидая Employee.EmployeeId, который не был передан из вашего запроса на публикацию, состояние вашей модели становится ложным.
Чтобы это исправить, вам следует включить следующий код в форму редактирования.
<input type = "hidden" asp-for = "EmployeeId" />
Обновленный код должен быть:
Вид:
@model Nexus.Models.Employee
<div class = "row">
<div class = "col-md-4">
<form asp-action = "EditEmployee" asp-controller = "Admin" method = "post">
<input type = "hidden" asp-for = "EmployeeId" />
<div class = "form-group">
<label class = "control-label">Name</label>
<input asp-for = "Name" class = "form-control" />
<span class = "text-danger" asp-validation-for = "Employee.Name"></span>
</div>
<div class = "form-group">
<label class = "control-label">Email</label>
<input asp-for = "Email" class = "form-control" />
<span class = "text-danger" asp-validation-for = "Employee.Email"></span>
</div>
<div class = "form-group">
<label class = "control-label">Password</label>
<input asp-for = "Password" class = "form-control" />
<span class = "text-danger" asp-validation-for = "Employee.Password"></span>
</div>
<div class = "form-group">
<label class = "control-label">Role</label>
<select asp-for = "RoleId" class = "form-control" asp-items = "Model.RoleList"></select>
<span class = "text-danger" asp-validation-for = "Employee.RoleId"></span>
</div>
<div class = "form-group">
<label class = "control-label">Shop address</label>
<select asp-for = "ShopId" class = "form-control" asp-items = "Model.ShopList"></select>
<span class = "text-danger" asp-validation-for = "Employee.ShopId"></span>
</div>
<br />
<div class = "form-group">
<input type = "submit" value = "Submit" class = "btn btn-primary" />
</div>
</form>
</div>
</div>
Контроллер:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditEmployee([Bind("EmployeeId,Name,Email,Password,RoleId,ShopId")] Employee employee)
{
var existingEmployee = _context.FirstOrDefault(e => e.EmployeeId == employee.EmployeeId);
if (existingEmployee == null)
{
return NotFound();
}
if (ModelState.IsValid)
{
existingEmployee.Name = employee.Name;
existingEmployee.Email = employee.Email;
existingEmployee.Password = employee.Password;
existingEmployee.RoleId = employee.RoleId;
existingEmployee.ShopId = employee.ShopId;
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
var viewModel = new EmployeeIndexViewModel
{
Employee = employee,
RoleList = new List<SelectListItem>
{
new SelectListItem { Value = "1", Text = "Admin" },
new SelectListItem { Value = "2", Text = "User" }
},
ShopList = new List<SelectListItem>
{
new SelectListItem { Value = "1", Text = "Shop 1" },
new SelectListItem { Value = "2", Text = "Shop 2" }
}
};
return View(viewModel);
}
Выход:
Примечание. Я протестировал сценарий с объектом класса, но если вы используете IFormCollection, не стесняйтесь менять свойство на своем контроллере.
Рад помочь вам в этом.
Вы проверили, какое значение вы получаете в контроллере, а какое не совпадает? Если привязка модели не совпадает, она всегда будет ложной.