天天看点

创建ASP.NET Core MVC应用程序(4)-添加CRUD动作方法和视图

参照VS自带的基架(Scaffold)系统-MVC Controller with views, using Entity Framework我们来创建CRUD方法。

① 将上一篇的Models/UserContext.cs文件中的用来指定使用的数据库逻辑的<code>OnConfiguring</code>方法删除,将逻辑移到Startup.cs文件中的<code>ConfigureServices</code>方法中。

② 在UserController.cs 构造函数中采用依赖注入来注入一个数据库上下文到该控制器。数据库上下文将被应用到控制器中的每一个CRUD方法。

③ 在UserController.cs中添加基本的CRUD方法:

一个<code>http://localhost:5000/User</code> 这样的请求到达User控制器后,将会从<code>User</code>表返回所有的数据,将将这些数据传递到<code>Index</code>视图:

④ 在Views/User文件夹中添加与上述Action方法名称相对应的Index.cshtml文件、Create.cshtml文件、Details.cshtml文件、Edit.cshtml文件、Delete.cshtml文件。

Create.cshtml运行效果:

Details.cshtml运行效果:

Edit.cshtml运行效果:

Delete.cshtml运行效果:

MVC提供了传递强类型对象给视图的能力,这样为你的代码提供了更好的编译时检查,并在VS中提供了更丰富的智能感知功能。

查看UserController/Details方法:

<code>id</code>参数通常作为路由数据来传递,比如 <code>http://localhost:5000/user/details/1</code> 会:

Controller设置为<code>user</code>(第一个URL段)

Action设置为<code>details</code>(第二个URL段)

id设置为1(第三个URL段)

你也可以通过查询字符串来传递<code>id</code>:

<code>http://localhost:5000/user/details?id=1</code>

如果指定的User被找到,则<code>User</code> Model实例将被传递到<code>Details</code>视图:

查看Views/User/Details.cshtml文件:

你会发现在顶部有一个<code>@model</code>语句,你可以指定视图所期望的对象类型。

<code>@model</code>指令允许你通过使用强类型的<code>Model</code>对象来访问从控制器传递到视图的User对象。例如,在Details.cshtml视图中,通过使用强类型的<code>Model</code>对象传递User的每一个字段到<code>DisplayNameFor</code>和<code>DisplayFor</code> HTML Helper。

再来查看Index.cshtml文件和User控制器中的<code>Index</code>方法。注意在调用View方法时,是如何创建一个<code>List</code>对象的。下面的代码将从<code>Index</code> Action方法传递整个<code>User</code>到视图中。

User控制器中的<code>Index</code>方法:

Index.cshtml文件最顶部:

<code>@model</code>指令允许你访问通过强类型的<code>Model</code>从控制器传递到视图的User列表。例如,在Index.cshtml视图中,在强类型的<code>Model</code>对象上通过<code>foreach</code>语句遍历了整个User列表:

首先,新建一个Repositories文件夹。在该文件夹下定义一个<code>IUserRepository</code>接口。

接着再添加一个<code>UserRepository</code>来实现<code>IUserRepository</code>接口。将之前定义的UserContext.cs逻辑移到该类中,在UserRepository.cs 构造函数中采用依赖注入来注入一个数据库上下文(UserContext)到该仓储类。数据库上下文将被应用到仓储类中的每一个CRUD方法。

再修改Controllers/UserController.cs文件,将<code>private readonly</code>的<code>UserContext</code>变量删除:

private readonly UserContext _context;

添加<code>IUserRepository</code>变量:

将所有方法中的<code>_context</code>操作删除,替换成<code>_userRepository</code>。例如,将<code>Index</code>方法中的<code>_context.Users.ToListAsync()</code>删除:

return View(await _context.Users.ToListAsync());

替换成

最终的UserController.cs如下:

通过定义Repository接口,从MVC Controller中解耦该repository类。通过注入一个UserRepository来代替直接在Controller里面实例化一个UserRepository类。

为了注入一个Repository到Controller,我们必须通过DI容器来注册它,打开Startup.cs文件,在ConfigureServices方法添加如下代码:

我们为Models/User.cs文件添加<code>Display</code>和<code>DataType</code>注解,首先要添加必要的命名空间<code>using System.ComponentModel.DataAnnotations;</code>:

再将属性在视图上显示成中文:

<code>Display</code> Attribute指定字段的显示名,<code>DataType</code>Attribute指定数据类型。

最终的显示效果如下:

打开Views/User/Index.cshtml,你会发现Edit,Details,Delete链接是由MVC Core Anchor Tag Helper生成的。

Tag Helpers允许服务器代码在Razor文件中参与创建和渲染HTML元素。在上述代码中,<code>AnchorTagHelper</code>从Controller Action动作方法和路由ID动态生成HTML<code>href</code>属性值。

查看Startup.cs中的<code>Configure</code>方法:

ASP.NET Core会将<code>http://localhost:5000/User/Edit/4</code> 转换成发送给<code>User</code>控制器的<code>Edit</code>方法(带有值为4的<code>Id</code>参数)的请求。

查看UserController.cs中的<code>[HttpPost]</code>版本的<code>Edit</code>方法:

<code>[Bind]</code> Attribute是一种防止over-posting(过度提交)的方式。应该只把你需要改变的属性包含到<code>[Bind]</code> Attribute中。

<code>[ValidateAntiForgeryToken]</code> Attribute是用来防止伪造请求的,会与Views/User/Edit.cshtml视图文件生成的反伪造标记(Token)进行配对。Views/User/Edit.cshtml视图文件通过Form Tag Helper来生成反伪造标记(Token)。

Form Tag Helper生成一个隐藏的防伪标记必须和<code>User</code>控制器中的<code>Eidt</code>方法的<code>[ValidateAntiForgeryToken]</code>产生的防伪标记相匹配。

查看Edit.cshtml,会发现基架系统(Scaffolding System)会为<code>User</code>类的每一个属性生成用来呈现的<code>&lt;label&gt;</code>和<code>&lt;input&gt;</code>元素。

基架代码使用了多个Tag Helper方法来简化HTML标记。

Label Tag Helper用来显示字段的名字。

Input Tag Helper用来呈现HTML<code>&lt;input&gt;</code>元素。

Validation Tag Helper用来显示关联属性的验证信息。

最终在浏览器中为<code>&lt;form&gt;</code>元素所生成的HTML如下:

HTML<code>&lt;form&gt;</code>中的<code>action</code>Attribute设置成POST到<code>/User/Edit/id</code>URL(所有<code>&lt;input&gt;</code>元素都在该<code>&lt;form&gt;</code>元素中)。当点击<code>Save</code>按钮时,表单数据会被发送(POST)到服务器。在<code>&lt;/form&gt;</code>元素的上面显示了Form Tag Helper所生成的隐藏的XSRF反伪造标记。

查看<code>[HttpPost]</code>版本的Edit方法:

<code>[ValidateAntiForgeryToken]</code>验证Form Tag Helper中的反伪造标记生成器所生成的隐藏的XSRF反伪造标记。

模型绑定(Model Binding)机制接受POST过来的表单数据并创建一个<code>User</code>对象并作为<code>user</code>参数。<code>ModelState.IsValid</code>方法验证从表单提交过来的数据可以用来修改一个<code>User</code>对象。如果数据有效,就可以进行保存。被更新的数据通过调用数据库的上下文(Database Context)的<code>SaveChangesAsync</code>方法来保存到数据库中。数据保存之后,代码将用户重定向到<code>UserController</code>类的<code>Index</code>方法。该页面会显示刚刚被改动后的最新的用户集合。

在表单被POST到服务器之前,客户端验证会检查所有字段上的验证规则,如果有任何验证错误,则会显示该错误信息,并且表单不会被发送到服务器。如果禁用了JS,将不会有客户端验证,但服务器会检测POST过来的数据是无效的,表单会重新显示错误信息。

Adding a model

over-posting

我的个人博客