
正文
创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段添加查询功能
本文将实现通过Name查询用户信息。
首先更新GetAll方法以启用查询:
public async Task<IEnumerable<User>> GetAll(string searchString)
{
var users = from u in _context.Users
select u; if (!string.IsNullOrEmpty(searchString))
{
users = users.Where(u => u.Name.Contains(searchString));
} return await users.ToListAsync();
}
第一行的LINQ查询仅仅在这里作了定义,并没有在这里实际操作数据库。
LINQ查询在被定义或者通过调用类似于Where、Contains、OrderBy的方法进行修改的时候不会执行。相反的,查询会延迟执行,比如在ToListAsync方法被调用之后。
Contains方法会在数据库中运行,而不是上面的C#代码,在数据库中,Contains会被映射成不区分大小写的SQLLIKE。
由于u => u.Name.Contains(searchString)Lambda表达式在当前我所使用的MySQL Connector/NET版本中运行报错(新版本好像已经修复了该问题,这里懒得更新了),所以这里先改成:
users = users.Where(u => u.Name == searchString);
导航到http://localhost:5000/User,添加?searchString=Zhu查询字符串,将过滤出指定的用户信息(http://localhost:5000/User?searchString=Zhu)。
如果你修改Index方法的签名使得方法包含一个名为id的参数,那么id参数将会匹配Startup.cs文件中设置的默认路由的可选项{id?}。
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Rename后的方法:
public async Task<IActionResult> Index(string id)
{
var users = from u in _context.Users
select u;
if (!String.IsNullOrEmpty(id))
{
users = users.Where(u => u.Name == id);
} return View(await users.ToListAsync());
}
现在你可以传递这个Name查询条件作为路由数据(URL Segment)来代替查询字符串(http://localhost:5000/User/Index/Zhu)。
然而,我们不能指望用户每次都通过修改URL来进行查询,我们通过添加UI来进行查询。如果你想改变Index方法的签名来测试怎样传递路由绑定ID参数,将searchString参数改回来。
接着,打开Views/User/Index.cshtml文件,添加<form>标记:
<form asp-controller="User" asp-action="Index">
<p>
姓名: <input type="text" name="SearchString">
<input type="submit" value="过滤" />
</p>
</form>
这里HTML<form>标签使用了Form Tag Helper,所以当你提交这个表单时,过滤字符串会被传递到User控制器的Index方法中。

这里没有使用你所希望的[HttpPost] Index重载方法,其实根本不需要该方法,因为这个方法并没有改变这个应用的状态,仅仅用来过滤数据。
你可以添加下面的[HttpPost] Index方法。
[HttpPost]
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}
notUsed参数用于创建一个重载的Index方法。如果你添加了该方法,动作方法将会调用匹配的[HttpPost] Index方法。
这个时候点击过滤按钮时,会显示如下界面:

然而,尽管你添加了[HttpPost]版本的Index方法,最终仍然存在局限性。想象你将一个指定的查询作为书签或者将查询结果作为一个链接发送给你的朋友以便他们在打开时能看到同样的过滤结果时,注意HTTP POST请求的URL和GET请求的URL(http://localhost:5000/User)是一样的-在URL里面没有任何查询信息。查询信息是作为表单数据发送到服务器的。

在请求体中可以看到查询参数和XSRF反伪造标记(通过Form Tag Helper生成),由于查询没有修改数据,所以无需在控制器方法中验证该标记。
为了把查询参数从请求体中移到URL中,必须把请求指定为HTTP GET。

<form asp-controller="Movies" asp-action="Index" method="get">
此时当你再提交时,URL将会包含具体的查询条件。查询将会跳转到HttpGet Index方法,即使存在着HttpPost Index方法。
添加新的字段
我们将通过Entity Framework Code First Migrations工具来添加一个新的字段到模型中,并将新的改变同步到数据库中。
当你使用EF Code First自动创建一个数据库时,Code First会添加一个表到数据库中帮助跟踪数据库的数据结构是否和模型类保持同步。如果不同步,EF会抛出一个异常。
添加身高属性到模型类
public class User
{
public int ID { get; set; }
[Display(Name = "姓名")]
public string Name { get; set; }
[Display(Name = "邮箱")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Display(Name = "简介")]
public string Bio { get; set; } // 新添加的属性
[Display(Name = "身高")]
public decimal Height { get; set; } [Display(Name = "职称")]
public string Title { get; set; } [Display(Name = "部门")]
public string Dept { get; set; }
}
Build该应用(dotnet build)。可能由于我所使用的MySQL EF Core provider还不成熟,添加DateTime类型的字段时会报错(新版本可能会修复该问题,这里懒得去测试了)。
由于你添加了一个新的字段到User类,所以你需要更新所绑定的白名单,这样新的属性将会包含这内。为Create和Edit方法更新[Bind]特性以包含Height属性。
[Bind("ID,Name,Email,Bio,Height,Title,Dept")]
为了显示新的字段还要更新视图模板。
打开Index.cshtml、Create.cshtml、Edit.cshtml等文件,添加新的Height字段。
然后需要更新数据库以包含新的字段。如果没有更新,此时运行将报错,因为更新后User模型类和已存在的数据库User表的结构不一致。
有以下几种方案来解决该错误:
EF可以基于新的模型类自动删除并重建数据库。开发阶段在测试数据库上做开发还是比较方便的,但是你会丢失数据库中的现有数据。因此该方案不适用于生产环境数据库!
显式修改现有数据库的结构,使得它与模型类相匹配,这个方案可以让你保留数据库的现有数据。你可以通过手动或者数据库脚本来进行变更。
使用Code First Migrations来更新数据库结构。
这里采用第三种方案,运行如下命令:
dotnet ef migrations add Height
dotnet ef database update
migrations add命令告诉Migration框架去检查当前的User模型类和当前的User数据库表结构是否一致。如果不一致,就创建必要的代码来迁移数据库到新的模型类。
基于新添加的“部门”字段进行查询
在Models目录下添加UserDeptViewModel类:
using Microsoft.AspNetCore.Mvc.Rendering;public class UserDeptViewModel
{
public List<User> users;
public SelectList depts;
public string userDept { get; set; }
}
这个视图模型(View Model)将包含:
- 用户列表
users。 - 包含部门列表(depts)的
SelectList,将用于视图页面中允许用户去从列表中选择一个部门。 userDept,包含用户所选中的部门(dept)。
修改Index方法:
public async Task<IActionResult> Index(string userDept, string searchString)
{
IQueryable<string> deptQuery = from u in _context.Users
orderby u.Dept
select u.Dept; var users = from u in _context.Users
select u;
if (!String.IsNullOrEmpty(searchString))
{
users = users.Where(u => u.Name == searchString);
} if (!String.IsNullOrEmpty(userDept))
{
users = users.Where(u => u.Dept == userDept);
} var userDeptVM = new UserDeptViewModel();
userDeptVM.depts = new SelectList(await deptQuery.Distinct().ToListAsync());
userDeptVM.users = await users.ToListAsync(); return View(userDeptVM);
}
下面的代码通过LINQ查询从数据库获取所有的部门数据。
IQueryable<string> deptQuery = from u in _context.Users
orderby u.Dept
select u.Dept;
depts的SelectList是通过投影不重复的部门(Distinct)创建的。
userDeptVM.depts = new SelectList(await deptQuery.Distinct().ToListAsync());
在Index视图中添加“部门”查询字段
首先删除最顶部的@model:
@model IEnumerable<MyFirstApp.Models.User>
替换成:
@model UserDeptViewModel
在<form>标记中添加:
<select asp-for="userDept" asp-items="Model.depts">
<option value="">所有</option>
</select>
在<table>标记中分别删除:
@Html.DisplayNameFor(model => model.Dept)
@foreach (var item in Model) {
替换成:
@Html.DisplayNameFor(model => model.users[0].Dept)
@foreach (var item in Model.users) {
最终的Index.cshtml文件如下:
@model UserDeptViewModel@{
ViewData["Title"] = "Index - User List";
}<h2>首页 - 用户列表</h2><p>
<a asp-action="Create">新建</a>
</p><form asp-controller="User" asp-action="Index" method="GET">
<p> <select asp-for="userDept" asp-items="Model.depts">
<option value="">所有</option>
</select> 姓名: <input type="text" name="SearchString">
<input type="submit" value="过滤" />
</p>
</form><table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.users[0].Name)
</th>
<th>
@Html.DisplayNameFor(model => model.users[0].Email)
</th>
<th>
@Html.DisplayNameFor(model => model.users[0].Height)
</th>
<th>
@Html.DisplayNameFor(model => model.users[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.users[0].Dept)
</th>
<th>
@Html.DisplayNameFor(model => model.users[0].Bio)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.users) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.DisplayFor(modelItem => item.Height)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Dept)
</td>
<td>
@Html.DisplayFor(modelItem => item.Bio)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">编辑</a> |
<a asp-action="Details" asp-route-id="@item.ID">详情</a> |
<a asp-action="Delete" asp-route-id="@item.ID">删除</a>
</td>
</tr>
}
</tbody>
</table>
最终运行的页面:

个人博客
我的个人博客
创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段的更多相关文章- 创建ASP.NET Core MVC应用程序(6)-添加验证
创建ASP.NET Core MVC应用程序(6)-添加验证 DRY原则 DRY("Don't Repeat Yourself")是MVC的设计原则之一.ASP.NET MVC鼓励 ...
- 创建ASP.NET Core MVC应用程序(4)-添加CRUD动作方法和视图
创建ASP.NET Core MVC应用程序(4)-添加CRUD动作方法和视图 创建CRUD动作方法及视图 参照VS自带的基架(Scaffold)系统-MVC Controller with view ...
- 创建ASP.NET Core MVC应用程序(1)-添加Controller和View
创建ASP.NET Core MVC应用程序(1)-添加Controller和View 参考文档:Getting started with ASP.NET Core MVC and Visual St ...
- 创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表
创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表 创建数据模型类(POCO类) 在Models文件夹下添 ...
- 创建ASP.NET Core MVC应用程序(2)-利用MySQL Connector NET连接到MySQL
创建ASP.NET Core MVC应用程序(2)-利用MySQL Connector NET连接到MySQL 用惯.NET的研发人员都习惯性地使用SQLServer作为数据库.然而.NET Core ...
- 跨平台应用集成(在ASP.NET Core MVC 应用程序中集成 Microsoft Graph)
作者:陈希章 发表于 2017年6月25日 谈一谈.NET 的跨平台 终于要写到这一篇了.跨平台的支持可以说是 Office 365 平台在设计伊始就考虑的目标.我在前面的文章已经提到过了,Micro ...
- 【翻译】使用Visual Studio创建Asp.Net Core MVC (一)
This tutorial will teach you the basics of building an ASP.NET Core MVC web app using Visual Studio ...
- 学习ASP.NET Core Razor 编程系列九——增加查询功能
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- ASP.NET Core MVC应用程序中的后台工作任务
在应用程序的内存中缓存常见数据(如查找)可以显着提高您的MVC Web应用程序性能和响应时间.当然,这些数据必须定期刷新. 当然你可以使用任何方法来更新数据,例如Redis中就提供了设定缓存对象的生命 ...
随机推荐- Scala深入浅出实战经典之 List伴生对象操作方法代码实战.
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Android(java)学习笔记126:Android Studio中build.gradle简介
1.首先我们直接上代码介绍: // Top-level build file where you can add configuration options common to all sub-pro ...
- Thread的run()与start()的区别
Java的线程是通过java.lang.Thread类来实现的.VM启动时会有一个由主方法所定义的线程.可以通过创建Thread的实例来创建新的线程.每个线程都是通过某个特定Thread对象所对应的方 ...
- u-boot添加一个hello命令
1.在common目录下建立一个cmd_hello.c文件 2.仿照/common/cmd_bootm.c文件修改,把cmd_bootm.c头文件复制过来 3.再复制do_bootm.U_BOOT_C ...
- 高仿QQ Xplan的H5页面
概述 这个h5的主要玩法很简单:地球自转的时候会播放背景音乐(比如海浪声),为了找到这个声音是从哪个地球上哪个地方传来的,需要长按下方的按钮,这时地球会自动转动到目标地点,然后镜头拉近,穿过云层,最后 ...
- web roadmap
- bat 脚本处理windows 文件
背景:以下脚本使用了导出文件列表.移动文件.复制文件.report 系统信息.分段执行的功能 主要针对在从事于Easeware公司中,对软件Bug中,所需文件的提取. 代码片段说明: cls ver ...
- qualcomm permission denied for tty device
在app中访问串口,提示没有读写权限.本文记录解决方法. 调试 查看设备节点权限 shell@msm8909:/ # ll /dev/ttyHSL* crw------- root root 246, ...
- Go工具和调试详解
https://blog.csdn.net/happyanger6/article/details/78724594/ https://blog.csdn.net/u012210379/article ...
- [Apache] Apache 從 2.2 換至 2.4 httpd.conf 的調整筆記 (windows 環境)
原文地址: http://www.dotblogs.com.tw/maplenote/archive/2012/07/20/apache24_httpd_conf.aspx 整理一下 Windows ...
创建ASP.NET Core MVC应用程序(6)-添加验证 DRY原则 DRY("Don't Repeat Yourself")是MVC的设计原则之一.ASP.NET MVC鼓励 ...
创建ASP.NET Core MVC应用程序(4)-添加CRUD动作方法和视图 创建CRUD动作方法及视图 参照VS自带的基架(Scaffold)系统-MVC Controller with view ...
创建ASP.NET Core MVC应用程序(1)-添加Controller和View 参考文档:Getting started with ASP.NET Core MVC and Visual St ...
创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表 创建数据模型类(POCO类) 在Models文件夹下添 ...
创建ASP.NET Core MVC应用程序(2)-利用MySQL Connector NET连接到MySQL 用惯.NET的研发人员都习惯性地使用SQLServer作为数据库.然而.NET Core ...
作者:陈希章 发表于 2017年6月25日 谈一谈.NET 的跨平台 终于要写到这一篇了.跨平台的支持可以说是 Office 365 平台在设计伊始就考虑的目标.我在前面的文章已经提到过了,Micro ...
This tutorial will teach you the basics of building an ASP.NET Core MVC web app using Visual Studio ...
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
在应用程序的内存中缓存常见数据(如查找)可以显着提高您的MVC Web应用程序性能和响应时间.当然,这些数据必须定期刷新. 当然你可以使用任何方法来更新数据,例如Redis中就提供了设定缓存对象的生命 ...
- Scala深入浅出实战经典之 List伴生对象操作方法代码实战.
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Android(java)学习笔记126:Android Studio中build.gradle简介
1.首先我们直接上代码介绍: // Top-level build file where you can add configuration options common to all sub-pro ...
- Thread的run()与start()的区别
Java的线程是通过java.lang.Thread类来实现的.VM启动时会有一个由主方法所定义的线程.可以通过创建Thread的实例来创建新的线程.每个线程都是通过某个特定Thread对象所对应的方 ...
- u-boot添加一个hello命令
1.在common目录下建立一个cmd_hello.c文件 2.仿照/common/cmd_bootm.c文件修改,把cmd_bootm.c头文件复制过来 3.再复制do_bootm.U_BOOT_C ...
- 高仿QQ Xplan的H5页面
概述 这个h5的主要玩法很简单:地球自转的时候会播放背景音乐(比如海浪声),为了找到这个声音是从哪个地球上哪个地方传来的,需要长按下方的按钮,这时地球会自动转动到目标地点,然后镜头拉近,穿过云层,最后 ...
- web roadmap
- bat 脚本处理windows 文件
背景:以下脚本使用了导出文件列表.移动文件.复制文件.report 系统信息.分段执行的功能 主要针对在从事于Easeware公司中,对软件Bug中,所需文件的提取. 代码片段说明: cls ver ...
- qualcomm permission denied for tty device
在app中访问串口,提示没有读写权限.本文记录解决方法. 调试 查看设备节点权限 shell@msm8909:/ # ll /dev/ttyHSL* crw------- root root 246, ...
- Go工具和调试详解
https://blog.csdn.net/happyanger6/article/details/78724594/ https://blog.csdn.net/u012210379/article ...
- [Apache] Apache 從 2.2 換至 2.4 httpd.conf 的調整筆記 (windows 環境)
原文地址: http://www.dotblogs.com.tw/maplenote/archive/2012/07/20/apache24_httpd_conf.aspx 整理一下 Windows ...








