参考文档:Getting started with ASP.NET Core MVC and Visual Studiohtml
这系列文章是参考了.NET Core文档和源码,可能有人要问,直接看官方的英文文档不就能够了吗,为何还要写这些文章呢?程序员
缘由以下:数据库
- 官方文档涉及的内容至关全面,属于那种大而全的知识仓库,不太适合初学者,很容易让人失去重要,让人掉入到具体的细节之中。
- 对于大多数人来说开发语言只是工具,程序员都有一个通病,就是死磕工具,把工具学深。我认为在工具上没有必要投入太多时间,以能高效地完成平常的工做项目为准便可。要需求驱动学习,你须要什么学什么。若是你学的新技术新特性只是屠龙之技或者只须要用到的时候去查一下便可的话,这种死磕这又有什么用。没有必要花120%的时间去学100%的知识,你只须要花20%的时间去学习80%的知识就能够了,剩下的等实际的项目中用到的时候去查就能够了,工具只是工具,不是工做自己。
- 目前基本全部的文章都是基于Windows平台的Visual Studio IDE来介绍的。而我用的是一台Mac,因此我将基于Mac平台的Visual Studio Code讲解适合咱们实际项目中遇到的知识。
- 还有一点,就是这是我我的的学习总结。
这系列文章就是让你去花20%的时间去学80%的东西,剩下的20%再去看官方文档。浏览器
以前介绍了《如何在Mac下运行ASP.NET Core应用程序》,主要是讲解了如何在Mac下把ASP.NET Core跑起来,在这一篇中将进一步分析如何添加Controller、View、Model等。架构
Model-View-Controller (MVC)架构模式将一个应用程序分红了三大块:Model、View、Controller。mvc
User
Model 从数据库获取用户数据,并将它交给View来显示或者直接更新,更新后的数据再写入到数据库中。MVC模式帮助你建立一个关注分离的应用程序(输入逻辑、业务逻辑、UI逻辑),同时这个模块之间是松耦合的。UI逻辑属于View,输入逻辑属于Controller,业务逻辑属于Model。app
namespace MyFirstApp.Controllers { public class HomeController : Controller { // GET: /<controller>/ public IActionResult Index() { return View(); } // GET: /<controller>/About public IActionResult About() { ViewData["Message"] = "Your application description page."; return View(); } public IActionResult Contact() { ViewData["Message"] = "Your contact page."; return View(); } public IActionResult Error() { return View(); } public IActionResult Welcome(string name, int id = 1) { ViewData["Message"] = "Hello " + name; ViewData["id"] = id; return View(); } } }
在控制器中的每个public
方法均可以做为HTTP终结点被调用。asp.net
第一个注释表示这是一个经过在根URL添加“/Home/”进行调用的HTTP GET方法。第二个注释表示这是一个经过在根URL添加"/Home/About/"来进行调用的HTTP GET方法。工具
MVC根据传入的请求URL调用相应的控制器类以及其中的Action方法,MVC默认使用的URL路由逻辑采用相似于这样的格式来决定具体的代码调用:布局
/[Controller]/[ActionName]/[Parameters]
打开Startup.cs
你会看到该项目的路由规则:
当你不带任何URL段(segment)直接运行该程序时,将默认访问“Home”控制器中的"Index"方法。
第一个URL segment决定运行哪一个Controller,因此http://localhost:5000/Home
映射到HomeController
类;URL segment第二个部分决定类里面的Action方法。因此http://localhost:5000/Home/Index
会运行HomeController
类中的Index
方法;URL segment的第三部分(id
)是路由数据。
这里经过增长一个方法来显示经过URL传递一些参数信息到Controller。
public string Welcome(string name, int id = 1) { return HtmlEncoder.Default.Encode($"Hello {name}, id: {id}"); }
上述代码经过使用HtmlEncoder.Default.Encode
来保护应用免受JS的恶意输入,而且使用了C#的新特性Interpolated Strings。
http://localhost:5000/Home/Welcome?name=Charlire&id=1
MVC的模型绑定系统自动将查询字符串的命名参数映射到具体的方法中的参数,注意名称必须一致。
上述代码中URL segment(Parameters
)没有被使用到,参数name
和id
都是做为查询字符串被传递的。?
是一个分隔符,后面跟着的就是查询字符串,&
用来分割查询字符串。
输入下面的URL:http://localhost:5000/Home/Welcome/1?name=Charlire
。这一次第三个URL segment将匹配到路由参数id
。Welcome
方法包含一个与MapRoute
方法中的URL模板相匹配的id
参数。随后的?
(id?
)表示id参数是可选的。
经过Razor视图引擎建立视图模板文件,基于Razor的视图模板使用 .cshtml 做为文件扩展名,经过使用C#提供了一个优雅的方式来建立HTML。
public IActionResult Index() { return View(); }
上面的Index
方法使用视图模板来生成一个HTML响应给浏览器。Controller中的Action方法一般返回一个IActionResult
(或一个派生于ActionResult
类),而不是像String这样的基元类型。
点击Views文件夹,在该文件夹下面新建与Controller名对应的文件夹。
而后咱们导航到Views->User文件夹,运行命令yo aspnet:mvcview Index
在该文件夹下面生成Index.cshtml。
Index
方法只是简单地运行了return View()
,来指定方法去使用一个视图模板文件来为浏览器渲染最新的响应。由于没有显式指定所要使用的视图模板文件,MVC会默认使用 /Views/User 文件夹中的 Index.cshtml。
通用点击菜单连接,你会发现每个页面都显示了相同的菜单布局,这个菜单布局位于 *Views/Shared/_Layout.cshtml* 文件。
Layout模板容许你在一个地方指定网站的HTML容器布局,并应用到网站的多个页面中。@RenderBody()
是一个占位符,用来显示你指定视图的位置,“包裹在”布局页面。举个例子,当你点击About连接,Views/Home/About.cshtml视图就会在RenderBody
方法内渲染。
注意如今每个页面都显示了新修改的连接,经过在Layout模板中修改一次,网站上的全部的页面都当即显示成新修改的信息。
经过查看 *Views/_ViewStart.cshtml* 文件:
@{ Layout = "_Layout"; }
*Views/_ViewStart.cshtml* 文件将 *Views/Shared/_Layout.cshtml* 文件引入到每个视图中。你能够经过Layout
属性来设置一个不一样的布局视图,或将它设置成null
,那么将不使用任何一个布局文件。
修改 Views/User/Index.cshtml 文件以下:
@{ ViewData["Title"] = "User List"; } <h2>User List</h2> <p>Hello from View Template!</p>
ViewData["Title"] = "User List";
将ViewDataDictionary
的Title
属性设置为User List
。这个Title
属性将用在 *Views/Shared/_Layout.cshtml* Layout页面的<title>
HTML元素上。
<title>@ViewData["Title"] - User MVC Application</title>
注意 Index.cshtml 视图模板中的内容是怎么和 *Views/Shared/_Layout.cshtml* 视图模板进行合并的,布局模板使得修改应用里全部的页面很容易。
在谈到数据库和模型(Models)以前,先让咱们讨论一下从控制器传递信息到视图。控制器方法会在传入的URL请求响应时被调用。控制器类是用于处理传入的浏览器请求,从数据库获取数据,并最终决定哪一种类型的的响应会被回传给浏览器。
控制器主要负责提供视图模板向浏览器呈现一个响应所需的数据或对象。
最佳实践:视图模板不该该执行业务逻辑或直接与数据库进行交互,而只应该使用控制器提供给它的数据。保持这样的“关注分离”有助于保持你的代码整洁,可测试性及更易于维护。
当前,HomeController
控制器中的Welcome
方法接受一个name
、id
参数,而后直接将值输出到浏览器。咱们在控制器中将使用一个视图模板来代替字符串,视图模板将生成一个动态响应,这就意味着你须要经过控制器传递适当的数据给视图来生成响应,可让控制器将视图模板须要的动态数据(参数)放入ViewData
字典中,随后视图模板能够经过访问该字典获取到这些数据。
ViewData
字典是一个动态对象,你能够将任何你想要的数据加进去。在你加入数据以前,ViewData
对象没有任何已定义的属性。MVC的模型绑定系统自动映射地址栏中查询字符串的命名参数到你方法中的参数。
public IActionResult Welcome(string name, int id = 1) { ViewData["Message"] = "Hello " + name; ViewData["id"] = id; return View(); }
ViewData
字典对象包括将要传递到视图的数据。接受,咱们来建立一个Welcome
视图模板。
这里将在Welcome.cshtml视图模板中建立一个循环。
@* For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 *@ @{ ViewData["Title"]= "Welcome Page"; } <h2>Welcome</h2> <ul> @for(int i=0; i<(int)ViewData["id"]; i++) { <li>@ViewData["Message"]</li> } </ul>
数据从URL得到并经过MVC模型绑定器传递到控制器,控制器将数据打包封装到ViewData
字典中并将该对象传递给视图。接着,视图将数据以HTML的形式渲染到浏览器。
咱们使用了一个ViewData
字典来将数据从控制器传递到视图,ViewData
字典是一个动态对象,它提供了一种便捷的后期绑定方式来传递信息给视图。接下来咱们将使用视图模型(View Model)来实现相同的目的。经过View Model来传递数据比经过ViewData
更受欢迎。