在本章中,我们将继续讨论标记助手.我们还将在我们的应用程序中添加一项新功能,并使其能够编辑现有员工的详细信息.我们将首先在每个员工的一侧添加一个链接,该链接将转到HomeController上的Edit操作.
@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>
我们还没有编辑操作,但我们需要一个可以编辑的员工ID.因此,让我们首先通过右键单击 Views → Home 文件夹创建一个新视图,然后选择 Add → 新商品.
In在中间窗格中,选择MVC View Page;调用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 tag helper,它说这是模型的Name属性的标签.此标记帮助程序可以将Html.For属性设置为具有正确的值,并设置此标签的内部文本,以便它实际显示我们想要的内容,例如员工姓名.
让我们转到HomeController类并添加编辑操作,该操作返回给用户提供编辑员工表单的视图,然后我们需要一秒钟编辑将响应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请求的编辑操作.它将需要一个员工ID.这里的代码类似于Details操作中的代码.我们将首先提取用户想要编辑的员工数据.我们还需要确保员工确实存在.如果它不存在,我们将用户重定向回Index视图.但是当员工存在时,我们将呈现编辑视图.
我们还需要回复表单将发送的HttpPost.
让我们在HomeController.cs文件中添加一个新类,如以下程序所示.
public class EmployeeEditViewModel { [Required, MaxLength(80)] public string Name { get; set; } }
在编辑操作中,将响应HttpPost将采用EmployeeEditViewModel,但不是员工本身,因为我们只想捕获Edit.cshtml文件中的表单项.
以下是编辑操作的实现.
[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中具有ID的URL传递,例如/home/edit/1 .
表单始终会回发到同一个URL ,/home/edit/1.
MVC框架将能够从URL中提取该ID并将其作为参数传递.
我们总是需要检查ModelState是否有效,并确保此员工在数据库中,并且在我们在数据库中执行更新操作之前它不是null .
如果都不是这样,我们将返回一个视图并允许用户再试一次.虽然在具有并发用户的实际应用程序中,如果员工为空,可能是因为员工删除了员工详细信息.
如果该员工没有'存在,告诉用户该员工不存在.
否则,请检查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; } } }
让我们编译程序并运行应用程序.
我们现在有一个编辑链接;让我们点击编辑链接编辑Josh的详细信息.
让我们将名称更改为Josh Groban.
点击保存按钮.
您可以看到该名称已更改为Josh Groban,如上面的屏幕截图所示.现在让我们点击主页链接.
在主页上,您将看到更新的名称.