控制器是ASP.NET Core 应用程序的大脑,它处理进入的请求,对模型提供的数据进行操作并且选择对应的View将数据呈现在浏览器中,控制器位于应用程序根目录的Controllers文件夹下,他们是普通的C#类,类里面包含的方法被称为Action方法,Action方法处理HTTP请求并向客户端发送Response响应,ASP.NET Core View负责将Controller发送的数据显示到浏览器端, 通过View我们也可以提交数据到Controller,View位于应用程序根目录的Views文件夹中,Views目录下的文件夹和Controller一一映射,在这些Controller文件夹内部,每个View是和Controller的方法一一映射的,例如:HomeController的视图位于Views->Home文件夹,相同的规律,StudentController的视图位于Views->Student.
首先创建一个ASP.NET Core MVC应用程序,命名为AspNetCore.Controllers, 打开Controllers目录,你会发现一个HomeController.cs, ASP.NET Core MVC为我们提供了一个默认的控制器

namespace AspNetCore.Controllers.Controllers{public class HomeController : Controller{private readonly ILogger<HomeController> _logger;public HomeController(ILogger<HomeController> logger){_logger = logger;}public IActionResult Index(){return View();}public IActionResult Privacy(){return View();}[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]public IActionResult Error(){return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });}}}
1 HomeController继承自Controller类
为了理解Controller的工作,我们只需要用Index方法,因此我们在Controller类中只保留Index方法把剩下的全部删除,删除完之后更新代码,更新完之后的代码如下:
using Microsoft.AspNetCore.Mvc;namespace AspNetCore.Controllers.Controllers{public class HomeController : Controller{private readonly ILogger<HomeController> _logger;public HomeController(ILogger<HomeController> logger){_logger = logger;}public IActionResult Index(){return View();}}}
@{ViewData["Title"] = "Home Page";}<div class="text-center"><h1 class="display-4">Welcome</h1><p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p></div>
@{ViewData["Title"] = "Home Page";}<div class="text-center"><p>Welcome from <b>Index View</b> of <b>Home Controller</p></div>
运行你应用程序,你将会看到这个视图呈现在浏览器中

2 ViewData什么是以及如何使用它
ViewData是一个ViewDataDictionary对象,可以通过字符串键来访问该对象,它本质是一个字典并且可以使用它把值从Controllers传递到Views或者也可以从Views传递到Layout View,在我们视图中,我们设置ViewData对象ViewData["Title"] = "Home Page",在layout视图中读取这个值(Views->Shared文件). layout试图使用它来设置页面的标题

你能使用ViewData传输任何类型的值像简单类型(strings,int,float) 或者类对象,下面例子我使用2个ViewData对象:
1 存储person的name属性值
public IActionResult SomeAction(){ViewData["Name"] = "GuiBingBing";ViewData["Address"] = new Address{HouseNo = "",City = ""};return View();}
现在在视图上,我展示2个ViewData对象中的值:
@{// casting address to Address.cs class objectvar address = ViewData["Address"] as Address;}<p>Hello: @ViewData["Name"]</p><p>With Address: @address.HouseNo, @address.City</p>
ControllerBase类是一个抽象的类不支持使用视图工作,当我们构建WebApi时我们可以让控制器继承自这个类
我们修改一下HomeController的Index视图
@{ViewData["Title"] = "Home Page";}<form class="form-horizontal" method="post" asp-action="ReceivedDataByRequest"><div class="mb-3 row"><div class="col-sm-1"><label>名称:</label></div><div class="col-sm-11"><input class="form-control" name="name" /></div></div><div class="mb-3 row"><div class="col-sm-1"><label>性别:</label></div><div class="col-sm-11"><select class="form-control" name="sex"><option value="M">Male</option><option value="F">Female</option></select></div></div><div class="mb-3 row"><div class="col-sm-11 offset-sm-1"><button type="submit" class="btn btn-primary">提交</button></div></div></form>
在表单上使用Bootstrap的样式表,来改善表单呈现效果
添加了2个HTML标签 - 一个为输入框 & 一个为下拉选择框,用户将填充或者选择一个值在下拉框中,点击提交按钮,这些控件的值将被传输到控制器,我们将显示这些值,注意这两个控件的名称是name和sex label仅仅是为了显示文本
public IActionResult ReceivedDataByRequest(){var name = Request.Form["name"];var sex = Request.Form["sex"];return View("ReceivedDataByRequest", $"{name} sex is {sex}");}
View("ReceivedDataByRequest", $"{name} sex is {sex}");第一个参数表示呈现的视图的名称,第二个参数传输到View的数据
现在我们针对这个方法创建一个视图文件,因此右击Views->Home文件夹并且选择Add->New Item,然后对话框选择
Razor View-Empty 选项并且命名视图ReceivedDataByRequest在视图中添加下面代码:
@model string<h1>@Model</h1>

视图的数据能够非常容易的传输到Action方法参数中,让我们做一个简单的解释,我们表单有2个html控件允许用户输入他们自己的名称和性别,我们可以在action方法中添加参数用来接收这两个控件的值,但是需要注意参数的名称必须和这两个控件的名称相同
public IActionResult ReceivedDataByParameter(string name, string sex){return View("ReceivedDataByParameter", $"{name} sex is {sex}");}
注意action方法的两个参数-name&sex, 他们的名字和控件的名字是相同的这点需要注意,因为name和sex的值是字符串类型,我们需要提供2个字符串类型的值,如果你想访问一个新的字段"age"的值你需要在action方法中添加一个新的int类型的参数
修改一下Index视图,asp-action="ReceivedDataByRequest"
标签修改为asp-action="ReceivedDataByParameter"这将改变表单的action属性为ReceivedDataByParameter,因此当我们点击提交按钮时ReceivedDataByParameter方法将调用,代码如下:
public IActionResult ReceivedDataByParameter(string name, string sex){return View("ReceivedDataByParameter", $"{name} sex is {sex}");}
最后,添加一个新的Razor视图在Views->Home文件夹,命名为ReceivedDataByParameter,这个视图将显示如下信息
@model string<h1>@Model</h1>

3.3 使用查询字符串将视图的值传递到控制器
<a href="/Home/ReceivedDataByParameter?name=jack sparrow&sex=m" class="link-primary">Primary link</a>最后,为了在控制器中接收值,在action方法中添加模型类型,让我们通过一个例子来演示一下
我们在Models文件夹下创建一个Person的类,包含如下代码:
namespace AspNetCore.Controllers.Models{public class Person{public string name { get; set; }public string sex { get; set; }}}
public IActionResult ReceivedDataByModelBinding(Person person){return View("ReceivedDataByModelBinding", person);}
@model Person<h1>@Model.name sex is @Model.sex</h1>
@model Person@{ViewData["Title"] = "Home Page";}@*<form class="form-horizontal" method="post" asp-action="ReceivedDataByRequest">*@@*<form class="form-horizontal" method="post" asp-action="ReceivedDataByParameter">*@<form class="form-horizontal" method="post" asp-action="ReceivedDataByModelBinding"><div class="mb-3 row"><div class="col-sm-1"><label>名称:</label></div><div class="col-sm-11">@*<input class="form-control" name="name" />*@<input class="form-control" asp-for="name" /></div></div><div class="mb-3 row"><div class="col-sm-1"><label>性别:</label></div><div class="col-sm-11">@*<select class="form-control" name="sex">*@<select class="form-control" asp-for="sex"><option value="M">Male</option><option value="F">Female</option></select></div></div><div class="mb-3 row"><div class="col-sm-11 offset-sm-1"><button type="submit" class="btn btn-primary">提交</button></div></div></form>
这里需要注意几点
1 这个视图接收的模型类型是person - @model Person
2表单asp-action帮助标签的值被修改为ReceivedData-ByModelBinding
3使用Person类的name和sex属性来绑定html控件的(input&select),使用模型类的属性绑定asp-for="class_property"绑定这些控件

我们使用ASP.NET Core创建一个上传文件的功能,注意我们提交表单使用POST方法并且设置enctype="multipart/form-data"
在Index视图添加下面代码,我们没有使用"asp-action"标记指定方法名称,默认调用我们Home控制器中的Index方法,同时注意上传文件类型的控件为file,控件的名称为photo
<form method="post" enctype="multipart/form-data"><div class="form-group"><label>Photo:</label><input type="file" class="form-control" name="photo" /></div><div class="m-1"><button class="btn btn-primary" type="submit">Upload</button></div></form>
接下来在Home控制器中添加一个Post版本的Index方法并且包含了IFormFile photo参数获取上传的文件,我们上传这个文件到wwwroot文件因此我必须注入IWebHostEnvironment在控制器的构造函数中
[HttpPost]public async Task<IActionResult> Index(IFormFile photo){using (var stream = new FileStream(Path.Combine(_hostingEnvironment.WebRootPath, photo.FileName), FileMode.Create)){await photo.CopyToAsync(stream);}return View();}
这节我们主要介绍了从把数据从View传输到Controller的几种方式,第一种方式使用Request.Form,第二种方式使用参数,第三种方式使用查询字符串,第四种方式使用模型绑定
https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/Fundamentals/AspNetCore.Controllers/AspNetCore.Controllers