В этой главе мы продолжим обсуждение помощников по тегам. Мы также добавим новую функцию в наше приложение и дадим ему возможность редактировать данные существующего сотрудника. Мы начнем с добавления ссылки на стороне каждого сотрудника, которая перейдет к действию «Изменить» на HomeController.
@model HomePageViewModel @{ ViewBag.Title = "Home"; } <h1>Welcome!</h1> <table> @foreach (var employee in Model.Employees) { <tr> <td>@employee.Name</td> <td> <a asp-controller = "Home" asp-action = "Details" asp-routeid = "@employee.Id">Details</a> <a asp-controller = "Home" asp-action = "Edit" asp-routeid = "@employee.Id">Edit</a> </td> </tr> } </table>
У нас еще нет действия Изменить, но нам потребуется идентификатор сотрудника, который мы можем редактировать. Итак, давайте сначала создадим новый вид, щелкнув правой кнопкой мыши на папке « Виды» → «Главная » и выбрав « Добавить» → «Новые элементы» .
На средней панели выберите страницу просмотра MVC; зайдите на страницу Edit.cshtml. Теперь нажмите на кнопку Добавить.
Добавьте следующий код в файл Edit.cshtml .
@model Employee @{ ViewBag.Title = $"Edit {Model.Name}"; } <h1>Edit @Model.Name</h1> <form asp-action="Edit" method="post"> <div> <label asp-for = "Name"></label> <input asp-for = "Name" /> <span asp-validation-for = "Name"></span> </div> <div> <input type = "submit" value = "Save" /> </div> </form>
Для заголовка этой страницы мы можем сказать, что мы хотим отредактировать, а затем указать имя сотрудника.
-
Знак доллара перед правкой позволит среде выполнения заменить Model.Name значением, которое находится в этом свойстве, например, имя сотрудника.
-
Внутри тега формы мы можем использовать помощники тегов, такие как asp-action и asp-controller. так что когда пользователь отправляет эту форму, он переходит непосредственно к определенному действию контроллера.
-
В этом случае мы хотим перейти к действию Edit на том же контроллере, и мы хотим явно сказать, что для метода в этой форме он должен использовать HttpPost.
-
По умолчанию для формы используется метод GET, и мы не хотим редактировать сотрудника с помощью операции GET.
-
В теге label мы использовали помощник тега asp-for, который говорит, что это метка для свойства Name модели. Этот помощник по тегам может настроить атрибут Html.For, чтобы он имел правильное значение и задавать внутренний текст этой метки, чтобы он действительно отображал то, что мы хотим, например, имя сотрудника.
Знак доллара перед правкой позволит среде выполнения заменить Model.Name значением, которое находится в этом свойстве, например, имя сотрудника.
Внутри тега формы мы можем использовать помощники тегов, такие как asp-action и asp-controller. так что когда пользователь отправляет эту форму, он переходит непосредственно к определенному действию контроллера.
В этом случае мы хотим перейти к действию Edit на том же контроллере, и мы хотим явно сказать, что для метода в этой форме он должен использовать HttpPost.
По умолчанию для формы используется метод GET, и мы не хотим редактировать сотрудника с помощью операции GET.
В теге label мы использовали помощник тега asp-for, который говорит, что это метка для свойства Name модели. Этот помощник по тегам может настроить атрибут Html.For, чтобы он имел правильное значение и задавать внутренний текст этой метки, чтобы он действительно отображал то, что мы хотим, например, имя сотрудника.
Давайте перейдем к классу HomeController и добавим действие Edit, которое возвращает представление, которое дает пользователю форму для редактирования сотрудника, а затем нам потребуется второе действие Edit, которое будет реагировать на HttpPost, как показано ниже.
[HttpGet] public IActionResult Edit(int id) { var context = new FirstAppDemoDbContext(); SQLEmployeeData sqlData = new SQLEmployeeData(context); var model = sqlData.Get(id); if (model == null) { return RedirectToAction("Index"); } return View(model); }
Во-первых, нам нужно действие редактирования, которое будет отвечать на запрос GET. Это займет идентификатор сотрудника. Код здесь будет похож на код, который мы имеем в действии Details. Сначала мы извлечем данные сотрудника, которые пользователь хочет отредактировать. Мы также должны убедиться, что работник действительно существует. Если он не существует, мы перенаправим пользователя обратно в представление индекса. Но когда сотрудник существует, мы будем отображать представление Edit.
Мы также должны ответить на HttpPost, который отправит форма.
Давайте добавим новый класс в файл HomeController.cs, как показано в следующей программе.
public class EmployeeEditViewModel { [Required, MaxLength(80)] public string Name { get; set; } }
В действии Edit, которое ответит на HttpPost, примет EmployeeEditViewModel, но не самого сотрудника, потому что мы хотим захватывать только те элементы, которые находятся в форме в файле Edit.cshtml.
Ниже приведена реализация действия Edit.
[HttpPost] public IActionResult Edit(int id, EmployeeEditViewModel input) { var context = new FirstAppDemoDbContext(); SQLEmployeeData sqlData = new SQLEmployeeData(context); var employee = sqlData.Get(id); if (employee != null && ModelState.IsValid) { employee.Name = input.Name; context.SaveChanges(); return RedirectToAction("Details", new { id = employee.Id }); } return View(employee); }
Форма редактирования всегда должна доставляться с URL, который имеет идентификатор в URL в соответствии с нашими правилами маршрутизации, например, / home / edit / 1 .
-
Форма всегда будет публиковаться по тому же URL, / home / edit / 1.
-
Инфраструктура MVC сможет извлечь этот идентификатор из URL и передать его в качестве параметра.
-
Нам всегда нужно проверять, является ли ModelState допустимым, а также убедиться, что этот сотрудник находится в базе данных, и он не является нулевым, прежде чем мы выполним операцию обновления в базе данных.
-
Если ничего из этого не соответствует действительности, мы вернем представление и позволим пользователю повторить попытку. Хотя в реальном приложении с одновременными пользователями, если сотрудник является нулевым, это может быть связано с тем, что кто-то удалил данные сотрудника.
-
Если этот сотрудник не существует, скажите пользователю, что сотрудник не существует.
-
В противном случае проверьте ModelState. Если ModelState недействителен, тогда верните представление. Это позволяет исправить редактирование и сделать ModelState допустимым.
-
Скопируйте имя из модели представления ввода для сотрудника, полученного из базы данных, и сохраните изменения. Метод SaveChagnes () будет сбрасывать все эти изменения в базу данных.
Форма всегда будет публиковаться по тому же URL, / home / edit / 1.
Инфраструктура MVC сможет извлечь этот идентификатор из URL и передать его в качестве параметра.
Нам всегда нужно проверять, является ли ModelState допустимым, а также убедиться, что этот сотрудник находится в базе данных, и он не является нулевым, прежде чем мы выполним операцию обновления в базе данных.
Если ничего из этого не соответствует действительности, мы вернем представление и позволим пользователю повторить попытку. Хотя в реальном приложении с одновременными пользователями, если сотрудник является нулевым, это может быть связано с тем, что кто-то удалил данные сотрудника.
Если этот сотрудник не существует, скажите пользователю, что сотрудник не существует.
В противном случае проверьте ModelState. Если ModelState недействителен, тогда верните представление. Это позволяет исправить редактирование и сделать ModelState допустимым.
Скопируйте имя из модели представления ввода для сотрудника, полученного из базы данных, и сохраните изменения. Метод SaveChagnes () будет сбрасывать все эти изменения в базу данных.
Ниже приведена полная реализация HomeController.
using Microsoft.AspNet.Mvc; using FirstAppDemo.ViewModels; using FirstAppDemo.Services; using FirstAppDemo.Entities; using FirstAppDemo.Models; using System.Collections.Generic; using System.Linq; using System.ComponentModel.DataAnnotations; namespace FirstAppDemo.Controllers { public class HomeController : Controller { public ViewResult Index() { var model = new HomePageViewModel(); using (var context = new FirstAppDemoDbContext()) { SQLEmployeeData sqlData = new SQLEmployeeData(context); model.Employees = sqlData.GetAll(); } return View(model); } public IActionResult Details(int id) { var context = new FirstAppDemoDbContext(); SQLEmployeeData sqlData = new SQLEmployeeData(context); var model = sqlData.Get(id) if (model == null) { return RedirectToAction("Index"); } return View(model); } [HttpGet] public IActionResult Edit(int id) { var context = new FirstAppDemoDbContext(); SQLEmployeeData sqlData = new SQLEmployeeData(context); var model = sqlData.Get(id); if (model == null) { return RedirectToAction("Index"); } return View(model); } [HttpPost] public IActionResult Edit(int id, EmployeeEditViewModel input) { var context = new FirstAppDemoDbContext(); SQLEmployeeData sqlData = new SQLEmployeeData(context); var employee = sqlData.Get(id); if (employee != null && ModelState.IsValid) { employee.Name = input.Name; context.SaveChanges(); return RedirectToAction("Details", new { id = employee.Id }); } return View(employee); } } public class SQLEmployeeData { private FirstAppDemoDbContext _context { get; set; } public SQLEmployeeData(FirstAppDemoDbContext context) { _context = context; } public void Add(Employee emp) { _context.Add(emp); _context.SaveChanges(); } public Employee Get(int ID) { return _context.Employees.FirstOrDefault(e => e.Id == ID); } public IEnumerable<Employee> GetAll() { return _context.Employees.ToList<Employee>(); } } public class HomePageViewModel { public IEnumerable<Employee> Employees { get; set; } } public class EmployeeEditViewModel { [Required, MaxLength(80)] public string Name { get; set; } } }
Давайте скомпилируем программу и запустим приложение.
Теперь у нас есть ссылка «Изменить»; давайте отредактируем детали Джоша, нажав на ссылку Изменить.
Давайте изменим имя на Джош Гробан.
Нажмите кнопку Сохранить.
Вы можете видеть, что имя было изменено на Джоша Гробана, как на скриншоте выше. Теперь давайте перейдем по ссылке Home.
На домашней странице вы увидите обновленное имя.