原文:ASP.NET Core Razor 编辑表单 - ASP.NET Core 基础教程 - 简单教程,简单编程

ASP.NET Core Razor 编辑表单

上一章节我们介绍了标签助手和 HTML 助手,也使用标签助手和 HTML 助手分别创建了一个职工列表,感觉好像有点喜欢上标签助手和 HTML 助手了,正好之前我们只讲解了如何列出数据,没有讲解如何创建表单来添加和修改数据

要不本章节我们就来讲讲? 顺带多用用标签助手和 HTML 助手

本章中,我们将继续讨论标签助手。 与此同时,还会给 HelloWorld 应用程序中添加一项新功能,并使其能够编辑现有员工的详细信息

我们将首先在每位员工旁边上添加一个链接,以便访问 HomeController 上的 "编辑" 操作,同时将页面美化一下

修改 Index.cshtml 为如下内容

@model HomePageViewModel
@{
ViewBag.Title = "职工列表";
}
<style>
body {margin:10px auto;text-align:center}
table {
margin:0 auto;
width:90% }
table, th, td {
border:1px solid #eee;
border-collapse:collapse;
border-spacing:0;
padding:5px;
text-align:center
} .txt-left {
text-align:left;
}
</style>
<h1>职工列表</h1>
<table>
<tr>
<td>ID</td>
<td>姓名</td>
<td class="txt-left">操作</td>
</tr>
@foreach (var employee in Model.Employees)
{
<tr>
<td>@employee.ID</td>
<td>@employee.Name</td>
<td class="txt-left"><a asp-action="Detail" asp-route-Id="@employee.ID">详情</a> &nbsp; <a asp-controller="Home" asp-action="Edit"
asp-route-id="@employee.ID">编辑</a></td>
</tr>
}
</table>

刷新浏览器,显示结果如下

如果我们此时点击任意一个 编辑 ,则会抛出 404 页面不存在错误

我们先来给 HomeController 添加一个 Edit 方法,接受一个 int 类型的 id 参数,然后返回一个 IActionResult 的结果,方法内容如下

[HttpGet]
public IActionResult Edit(int id)
{ var model = new HomePageViewModel();
SQLEmployeeData sqlData = new SQLEmployeeData(_context); Employee employee = sqlData.Get(id); if ( employee == null ) {
return RedirectToAction("Index");
} return View(employee);
}

这段代码出现了很多新面孔,比如 [HttpGet] 特性,有关 C# 特性的知识,请访问我们的 C# 基础教程:特性 ( Attribute )

ASP.NET Core 所有以 Http 开头的特性用于标识该方法只接受特定的 HTTP 请求方法

ASP.NET Core 支持下图七个 HTTP 请求方法特性

特性 说明
HttpGet 标识某个方法只支持 HTTP GET 请求方法
HttpPut 标识某个方法只支持 HTTP PUT 请求方法
HttpHead 标识某个方法只支持 HTTP HEAD 请求方法
HttpPost 标识某个方法只支持 HTTP POST 请求方法
HttpPatch 标识某个方法只支持 HTTP PATCH 请求方法
HttpDelete 标识某个方法只支持 HTTP DELETE 请求方法
HttpOptions 标识某个方法只支持 HTTP OPTIONS 请求方法

关于这些 HTTP 请求方法的介绍,可以访问我们的 HTTP 基础教程:HTTP 请求方法

第二个新面孔就是方法的返回值 IActionResult ,我们在 ASP.NET Core 动作结果 有提到,IActionResult 是所有返回结果的必须实现的接口,用这个作为返回值,也就是说该方法可以接受任意返回值。

第三个新面孔就是下面这段代码

if ( employee == null ) {
return RedirectToAction("Index");
}

意思是是如果 employee 的结果为空,也就是没有在数据库里找到 id 对应的记录,则重定向到 Index 方法,从某些方面说也就是重定向到首页

RedirectTo 家族非常庞大,数量之多,几乎涵盖了各种情况下的重定向

好了,重启我们的应用程序,然后刷新浏览器,自然,肯定是出错了,因为缺少对应的视图

那么,我们就在 Views/Home 下添加一个视图 Edit.cshtml 吧,添加方法和之前添加 Index.cshtmlDetail.cshtml 一样,我们就不做介绍了,然后输入以下内容

@model Employee
@{
ViewBag.Title = $"编辑 {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 = "保存" />
</div>
</form>

我们来解释下下面这段代码

保存我们的 Edit.cshtml,刷新浏览器,还是报错了。这次的错误是提示 Employee 类没有找到

修改 _ViewImports.cshtml 添加 @using HelloWorld.Models,添加完成后 _ViewImports.cshtml 的内容如下

@namespace HelloWorld.Views
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using HelloWorld.Controllers
@using HelloWorld.Models

保存,然后刷新浏览器,这回显示正确了

当然了,不管我们是否编辑了员工姓名,如果点击保存,还是会报错,提示 404 不存在

这是因为我们刚刚添加的方法只适用于 HTTP GET 请求方法

我们需要再重载一个 Edit 方法用于接受 HTTP POST 请求

[HttpPost]
public IActionResult Edit(int id, EmployeeEditViewModel input)
{
SQLEmployeeData sqlData = new SQLEmployeeData( _context );
var employee = sqlData.Get(id); if (employee != null && ModelState.IsValid)
{
employee.Name = input.Name;
_context.SaveChanges();
return RedirectToAction("Detail", new { id = employee.ID });
}
return View(employee);
}

根据我们的路由规则,编辑表单应始终使用包含了 id 的 URL 来传递,如 /home/edit/1, 而显示表单和提交表单数据的最大差别就是 HTTP 请求方法,提交表单使用 [HttpPost] 特性

ASP.NET Core MVC 框架可以从 URL 中提起 id 数据并作为参数传递给动作方法

至于表单传递的其它数据,比如员工姓名,则使用另一个模型来接受不了,这个模型就是 EmployeeEditViewModel

EmployeeEditViewModel

EmployeeEditViewModel 用来从 HTTP POST 请求方法中接受传递的表单数据

EmployeeEditViewModel 到底长啥样呢,其实它跟 HomePageViewModel 差不多

我们再添加一下代码到 HomePageViewModel 后面

public class EmployeeEditViewModel {
[Required, MaxLength(80)]
public string Name { get; set; }
}

HomePageViewModel 包含了一个属性 Name,注意,Name 的名称和大小写必须和表单一模一样。

然后使用 C# 特性来限制 Name 字段必须输入数据 ( Required ),且数据的最大长度不得超过 80 ( MaxLength(80) )

因为表单只有一个字段 Name ,所以模型也就只有一个属性 Name,很简单,我们就不多做阐述了。

最后,使用 Required 等注解需要引入命名空间 System.ComponentModel.DataAnnotations `

ASP.NET Core MVC 参数模型绑定

回到 public IActionResult Edit(int id, EmployeeEditViewModel input) 方法,相比你也很好奇,ASP.NET Core MVC 是怎么给我们的 Edit 的两个参数传递实际的值的

我查阅了很多文档,原来 ASP.NET Core 使用了一种叫 模型绑定 的方法

模型绑定 是将 HTTP 请求的各种数据映射到动作方法参数的一种方法,参数即可以是简单类型,如字符串、整数或浮点数,也可以是复杂类型,如一个类。

模型绑定 查找数据源的顺序是

  1. Form values: 通过 HTTP POST 方法提交的数据,例如 Name
  2. Route values: 路由器解析的参数,例如 id
  3. Query String: URI 中的查询字符串部分的数据,也就是 ? 后面那一串

而模型绑定按照上面的顺序,只要找到了数据,就会停止继续查找。假设我们我们的 URI 为 /home/edit/1 ,而我们的表单有一个字段 id 值为 2 ,那么 Edit 方法的值为 2 而不是一,这是因为已经在 Form 表单中找到了 id 值,所以就不会继续查找了

对于复杂的数据,比如 HomePageViewModel,它的属性也是有要求的

  1. 要求接收数据的属性必须是 public 的,如果不是,那么就没法注入值
  2. 要求必须有一个无参数的构造函数

当发生绑定时,类只会使用公共默认构造函数来实例化,然后在设置属性值。

ModelState

当一个参数绑定了数据后,模型绑定就会停止查找该名称的值,并继续绑定下一个参数。

如果某个参数绑定失败,那么 MVC 框架也不会抛出任何错误,而是设置 ModelState 的属性为 false,仅此而已

因此,我们可以通过检查 ModelState 的值来检查数据格式是否正确

_context.SaveChanges();

_context.SaveChanges(); 用于保存验证后的数据到数据库

其实 模型绑定 还有很多内容,但是限于篇幅,我们就不再继续了,如果你想深入阅读,可以查阅 ASP.NET 官方文档

运行范例

我们回到 HomeController.cs,当所有的修改完成后,完整的代码如下

HomeController

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq; using HelloWorld.Models; namespace HelloWorld.Controllers
{
public class HomeController: Controller
{ private readonly HelloWorldDBContext _context; public HomeController(HelloWorldDBContext context)
{
_context = context;
} public ViewResult Index()
{ var model = new HomePageViewModel();
SQLEmployeeData sqlData = new SQLEmployeeData(_context);
model.Employees = sqlData.GetAll(); return View(model);
} public ViewResult Detail(int id)
{ var model = new HomePageViewModel();
SQLEmployeeData sqlData = new SQLEmployeeData(_context); Employee employee = sqlData.Get(id); return View(employee);
} [HttpGet]
public IActionResult Edit(int id)
{ var model = new HomePageViewModel();
SQLEmployeeData sqlData = new SQLEmployeeData(_context); Employee employee = sqlData.Get(id); if ( employee == null ) {
return RedirectToAction("Index");
} return View(employee);
} [HttpPost]
public IActionResult Edit(int id, EmployeeEditViewModel input)
{
SQLEmployeeData sqlData = new SQLEmployeeData( _context );
var employee = sqlData.Get(id); if (employee != null && ModelState.IsValid)
{
employee.Name = input.Name;
_context.SaveChanges();
return RedirectToAction("Detail", new { id = employee.ID });
}
return View(employee);
} } public class SQLEmployeeData
{
private HelloWorldDBContext _context { get; set; } public SQLEmployeeData(HelloWorldDBContext 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; }
}
}

保存 HomeController.cs,重启应用程序,然后刷新浏览器,结果如下

点击 ID1编辑,显示如下

我们将 李白 改成 李太白

点击保存

然后点击返回首页

ASP.NET Core MVC 的基础教程终于学习完了

ASP.NET Core Razor 编辑表单 - ASP.NET Core 基础教程 - 简单教程,简单编程的更多相关文章

  1. ASP.NET MVC 音乐商店 - 5. 通过支架创建编辑表单

    在上一章,我们已经从数据库获取数据,然后显示出来,这一章,我们将允许编辑数据. 创建 StoreManagerController 控制器 我们将要创建称为 StoreManager 的控制器,对于这 ...

  2. ASP.NET MVC 3 之表单和 HTML 辅助方法(摘抄)

    ——选自<ASP.NET MVC3 高级编程(第5章) 孙远帅 译> 第5章 表单和HTML辅助方法 本章内容简介: * 理解表单 * 如何利用HTML辅助方法 * 编辑和输入的辅助方法 ...

  3. ASP.NET MVC3学习心得-----表单和HTML辅助方法

    5.1表单的使用 5.1.1  action和method的特性 表单是包含输入元素的容器,包含按钮.复选框.文本框等元素,表单的这些输入元素使得用户能够向页面中输入信息,并把输入信息提交给服务器.A ...

  4. ASP.NET Web Pages:表单

    ylbtech-.Net-ASP.NET Web Pages:表单 1.返回顶部 1. ASP.NET Web Pages - HTML 表单 表单是 HTML 文档中放置输入控件(文本框.复选框.单 ...

  5. C# Winform 通过FlowLayoutPanel及自定义的编辑控件,实现快速构建C/S版的编辑表单页面

    个人理解,开发应用程序的目的,不论是B/S或是C/S结构类型,无非就是实现可供用户进行查.增.改.删,其中查询用到最多,开发设计的场景也最为复杂,包括但不限于:表格记录查询.报表查询.导出文件查询等等 ...

  6. Winform 通过FlowLayoutPanel及自定义的编辑控件,实现快速构建C/S版的编辑表单页面 z

    http://www.cnblogs.com/zuowj/p/4504130.html 不论是B/S或是C/S结构类型,无非就是实现可供用户进行查.增.改.删,其中查询用到最多,开发设计的场景 也最为 ...

  7. atitit.提升开发效率---MDA 软件开发方式的革命(4)----编辑表单建模

    )----编辑表单建模 1. 建模语言的选型anno+html...不是uml 1 2. 指定显示模板 @BeanEditForm(tmplt="c:/edit.html") 1 ...

  8. 【jQuery EasyUI系列】 创建展开行明细编辑表单的CRUD应用

    当切换数据网络格局(datagrid view)到detailview,用户可以展开一行来显示一些行的明细在行下面,这个功能允许您为防止在明细行面板中的编辑表单提供一些合适的布局. 步骤1.在HTML ...

  9. atitit.编辑表单的实现最佳实践dwr jq easyui

    atitit.编辑表单的实现最佳实践dwr jq easyui 1. 提交表单 1 2. 表单验证 1 3. 数据保存使用meger方式取代save&update方式 1 3.1. Filte ...

随机推荐

  1. 神奇校车 = topsage

    https://post.smzdm.com/p/6356/ 适合6岁至99岁的小盆友看的<The Magic School Bus> (神奇校车) http://club.topsage ...

  2. Json入门 分类: C_OHTERS 2014-04-23 16:20 601人阅读 评论(0) 收藏

    参考<疯狂android讲义>>730页 JSON的基础请参考W3SCHOOL的教程: http://www.w3school.com.cn/json/index.asp 例子: h ...

  3. ExtJS中store.findExact

    var ds = myGrid.apf_ds; var store = myGrid.getStore(); forEach(data, function (item) { if (store.fin ...

  4. 谈谈JavaEE的mvc模式及典型的三层架构

    首先,向读者介绍一下mvc架构,mvc是一种源于桌面程序的架构模式,它的基本思想是把程序界面和业务逻辑分开,这样便于软件的后期维护,同时也方便开发时期分工及管理,mvc有很多有点所以现在已经被广泛的应 ...

  5. Uncaught SyntaxError: Unexpected end of input 解决办法

    Unexpected end of input  的英文意思是"意外的终止输入" 他通常表示我们浏览器在读取我们的js代码时,碰到了不可预知的错误,导致浏览器 无语进行下面的读取 ...

  6. 基于 Android NDK 的学习之旅-----序言

    前些日子做了个Android项目, 引擎层 用C的, 准备写这个系类的文章,借此跟朋友来分享下我NDK开放的经验以及自己知识的总结和备忘.希望能给需要这方面资料的朋友提供一定的帮助. 主要涉及到:   ...

  7. 卡特兰(Catalan)数列

    卡特兰数又称卡塔兰数,英文名 Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列.以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名,其前几项为 : 1 ...

  8. [React] Use React Context to Manage Application State Through Routes

    We’ll create a Router component that will wrap our application and manage all URL related state. We’ ...

  9. MySQL经常使用的面试题

    1.怎样登陆mysql数据库 MySQL -u username -p 2.怎样开启/关闭mysql服务 service mysql start/stop 3.查看mysql的状态 service m ...

  10. Procedural graphics architectures and techniques

    BACKGROUND The evolution of graphics rendering technology has led to the development of procedural t ...