三、控制器
正如第一章所讨论的,所有 web 应用都从服务器接收请求并生成响应,然后返回给最终用户。 在 ASP 中,控制器接收请求并根据输入数据生成输出。 净 MVC。
在本章中,你将学习以下主题:
- 控制器在 ASP 中的作用。 净 MVC 应用
- 路由介绍和概念
- 创建您的第一个 ASP。 净 5 应用
- 安装 ASP.NET Core
NuGet
包 - 创建第一个控制器和
action
方法,它返回一个简单的Hello World - 添加一个视图,并做一些改变,以允许你的控制器使用那个视图
- 添加一个模型并将模型数据传递给视图
控制器在 ASP 中的作用 净 MVC 应用
在高层,控制器在模型和视图之间进行协调,并将输出发送回用户。 这也是通常通过操作过滤器进行身份验证的地方。 动作滤波器将在本章的滤波器部分详细讨论。 下图说明了在 ASP 中请求的高级流程(包括步骤).NET MVC,并向我们展示了控制器如何融入全局:
下面是用户访问 ASP 时在高层将发生的事件序列.NET Core 应用:
- 用户在浏览器中输入 URL。
- 路由引擎根据 URL 的模式选择适当的控制器。
- Controller 与 Model 对话,通过它的操作方法获取任何相关数据。 动作方法是
controller
类中的方法。 - 然后控制器将数据传递给视图,以一种可查看的格式(通常是 HTML 元素)显示数据。
- 视图最终被交付给用户,用户将在浏览器中查看视图。
在讨论控制器之前,让我们先讨论路由概念的基础知识,因为路由引擎在运行时只选择合适的controller
和action
方法。
路由介绍
路由引擎负责获取传入请求,并根据 URL 模式将该请求路由到适当的 Controller。 我们可以配置路由引擎,以便它可以根据相关信息选择适当的控制器。
按照惯例,ASP.NET MVC 遵循以下模式:Controller/Action/Id。
如果用户输入 URLhttp://yourwebsite.com/Hello/Greeting/1
,路由引擎选择HelloController
中的Hello controller
类和Greeting action
方法,并将Id
值作为1
传递。 您可以为某些参数设置默认值,并使某些参数成为可选参数。
配置示例如下:
The template: "{controller=Hello}/{action=Greeting}/{id?}");
在前面的配置中,我们给路由引擎提供了三条指令:
- 使用路由模式
controller/action/id
。 - 如果 URL 中没有提供
controller
或action
的值,则对controller
和action
分别使用默认值Hello
和Greeting
。 - 将
Id
参数设置为可选参数,这样 URL 就不需要包含这些信息。 如果 URL 包含这个Id
信息,它将使用它。 否则,Id
信息将不会传递给action
方法。
让我们来讨论路由引擎如何为不同的 url 选择controller
类、action
方法和Id
值:
URL1:http://localhost/
Controller: Hello
Action method: Greeting
Id: no value is passed for the id parameter
原因:根据路由配置,Hello
控制器作为默认值传递,因为 URL 中没有作为控制器传递值。
下面的action
方法将被路由处理程序在前面的 URL 被传递时拾取:
public class HelloController : Controller {
public ActionResult Greeting(int id) {
return View();
}
}
URL2: http://localhost/Hello/Greeting2
Controller: Hello
Action method: Greeting2
Id: no value is passed for the id parameter
推理:URL 包含Hello
作为第一个参数,选择Hello
控制器;URL 包含Greeting2
作为第二个参数,选择Greeting2
动作方法。 请注意,只有当 URL 中没有值时,才会选择配置中提到的默认值。 由于id
参数是可选的,且 URL 不包含id
的值,所以没有值传递给id
参数。
下面的动作方法Greeting2
将被路由处理程序拾取,当前面的 URL 被传递时:
public class HelloController : Controller {
public ActionResult Greeting(int id) {
return View();
}
public ActionResult Greeting2(int id) {
return View();
}
}
URL3: http://localhost/Hello2/Greeting2
Controller: Hello2
Action method: Greeting2
Id: no value is passed for the id parameter
推理:作为第一个参数传递Hello2
,选择Hello2
控制器,作为第二个参数传递Greeting2
,选择Greeting2
动作方法。 由于id
参数是可选的,并且没有为参数id
传递值,所以没有为id
传递值。
下面的action
方法将被路由处理程序在前面的 URL 被传递时拾取:
public class Hello2Controller : Controller {
public ActionResult Greeting2(int id) {
return View();
}
}
URL4: http://localhost/Hello3/Greeting2/1
Controller: Hello3
Action method: Greeting2
Id: 1
推理:Hello3
是作为第一个参数选择的控制器,Greeting4
是动作方法,1
是作为id
传递的值。
下面的action
方法将会在前面的 URL 被传递时被路由处理程序拾取:
public class Hello3Controller : Controller {
public ActionResult Greeting2(int id) {
return View();
}
}
我们将在后面的章节中详细讨论路由。
一旦请求到达控制器,控制器将通过与模型对话创建响应,并可能将数据传递给视图,然后视图将呈现给最终用户。
创建 ASP。 净 5 应用
是时候动手了。 让我们创建一个简单的 ASP。 净 5 应用。 启动 Visual Studio 并遵循以下步骤:
-
Create a project by selecting File | New Project in Visual Studio. The first option is for creating an earlier version of the ASP.NET Web application. The second option is for creating the ASP.NET Core application using the .NET Core framework. The third option is for creating the ASP.NET Core application using the .NET framework. The difference between the second and third option is that the .NET framework supports all the functionalities of existing .NET frameworks whereas .NET Core supports only the core functionalities. The advantage of using the .NET core library is that it can be deployed on any platform.
-
Select the Empty template from the list of ASP.NET 5 templates. The second option is for creating the Web API application (for building the HTTP-based services) and the third option is for creating a web application containing some basic functionalities which you can run just from out of the box without you ever needing to write anything.
-
Once you click OK in the window as shown in the preceding screenshot, (after selecting the Empty template option) a solution will be created as shown in the following screenshot:
-
When you run the application (by pressing F5 ) without any changes, you'll get the simple Hello World! text on your screen as shown in the following screenshot:
我们没有在这个新创建的应用中进行任何编码。 那么,您是否考虑过它如何显示文本Hello World! ?
答案在Startup.cs
文件中,该文件包含一个名为Startup
的类。 这个类包含了Main
方法,它作为 web 应用的入口点。 如果您使用过任何以前版本的 ASP.NET MVC,甚至 asp.net.NET Web 窗体,这将不是情况。
ASP.NET 5 运行时调用ConfigureServices
和Configure
方法。 例如,如果您想配置任何服务,您可以将其添加到这里。 您的应用的任何自定义配置都可以添加到这个Configure
方法:
public void ConfigureServices(IServiceCollection services) {
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app) {
app.UseIISPlatformHandler();
app.Run(async (context) => {
await context.Response.WriteAsync("Hello World!");
});
}
在Configure
方法中只有几个语句。 第一条语句告诉运行时使用IISPlatformHandler
来处理所有传入的 HTTP 请求。 让我们暂时把第二句中的async
、await
和context
放在一边,我们将在后面讨论。 实质上,第二条语句告诉运行时为所有传入的请求返回Hello World!
,而不管传入的 URL 是什么。
当您在浏览器中键入 URLhttp://localhost:50140/Hello
时,它仍然会返回相同的Hello World! 。
这就是我们得到Hello World 的原因! 当我们运行应用时。
因为我们在创建 ASP 的时候选择了空的模板.NET 5 应用,没有安装任何组件。 当你像我们一样选择了空模板时,MVC 也不会被默认安装。
您可以通过打开project.json
文件来确认它,在该文件中您看不到任何 ASP.NET MVC 在依赖项列表中被提到:
"dependencies": {
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final"
},
首先,让我们安装 ASP。 我们的应用的 Net Core 包。
安装 ASP.NET Core NuGet 包在您的应用
按照以下步骤安装 ASP 的NuGet
包.NET MVC:
-
Right click on the project, and select the Manage NuGet Packages option:
-
Select the Include Prerelease checkbox so that the NuGet Package Manager will list out all the prerelease packages. Search for
MVC
and you'll get the Microsoft.AspNet.MVC package, as shown in the following result, and click on the Install button on the right-hand side: -
Review the changes:
-
Once you click on Review Changes , the following dialog box will appear where you need to accept the license terms:
NuGet 包管理器将下载并安装 ASP.NET Core 和将更新project.json
文件和相关的引用。
现在,您的project.json
文件将有更新的依赖项。 添加了第二行Microsoft.AspNet.Mvc
:
"dependencies": {
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final"
},
另外,您还可以使用NuGet
包和版本信息更新project.json
。 NuGet 包管理器会自动下载并安装。
ASP.NET Core 安装在我们的应用中。 现在,我们需要告诉我们的应用使用 ASP。 净 MVC。
这需要对Startup.cs
文件做一些修改:
-
配置应用以添加 MVC 服务。 这可以通过在
Startup
类的ConfigureServices
方法中添加以下一行来实现:``` services.AddMvc();
```
-
配置路由,以便根据输入的 URL 为传入请求选择正确的控制器。 以下代码片段需要在
Startup.cs
文件的Configure
方法中更新:app。 路由=>{``` app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
```
在前面的语句中,我们正在为应用配置路由。
在本章以及本书的大部分章节中,我们将手动编写代码,或者选择一个空的模板,而不是依赖于脚手架模板。 对于那些不熟悉脚手架这个术语的人来说,脚手架是为所选项目(例如控制器)生成所有必要的样板代码的特性,而不是需要您编写所有内容。 虽然我同意搭建模板很有用,并且在生成样板代码时节省了时间,但它们隐藏了许多初学者必须理解的细节。 一旦您手动编写代码,您就会知道每个组件是如何对全局做出贡献的所有复杂之处。 一旦你掌握了足够的基础知识,你就可以使用脚手架模板来节省编写样板代码的时间。
第一个控制器
在创建控制器之前,我们需要删除下面的app.Run
语句,因为这将为所有传入的请求返回Hello World!
。 由于我们希望传入的请求由控制器处理,我们需要从Startup
类的Configure
方法中删除以下代码:
app.Run(async (context) => {
await context.Response.WriteAsync("Hello World!");
});
我们已经安装了 ASP。 在我们的应用中。 因此,我们准备好创建我们的第一个 ASP.NET Core 控制器。 创建一个名为Controllers
的文件夹,并通过从上下文菜单中选择添加一个新的控制器,如下图所示:
一旦您选择添加|新项目,您将看到以下选项列表。 我们将添加一个 MVC 控制器类到我们的项目:
将创建一个包含以下内容的类:
public class HomeController : Controller {
// GET: /<controller>/
public IActionResult Index() {
return View();
}
}
所有控制器,包括 MVC 和 Web API 控制器,都继承自Controller
基类。 在早期版本的 ASP.NET MVC, MVC 控制器将继承自Controller
类,Web API 控制器将继承自APIController
类。
在前面的HomeController
类中,我们有一个通过Index
返回相应视图的操作方法。 当您按原样运行应用时,您将得到一个500 内部服务器错误。 原因是没有为HomeController
和 ASP 的Index
操作创建视图.NET Core 尝试搜索那个视图。 由于视图不可用,它返回一个500 内部服务器错误。
让我们对这个操作方法做一个简单的更改,而不是创建并返回那个视图。 让我们返回一个字符串Hello World! I am learning MVC 6!
,并更改IActionResult
的返回类型:
public string Index() {
return "Hello World! I am learning MVC 6!";
}
运行应用。 你会看到Hello World! 我正在学习 MVC 6! ,如下截图所示。 请确保您在前面提到的Configure
方法中删除了app.Run
语句:
瞧! 我们已经改变了 ASP.NET Core 应用来渲染自定义内容,而不是无聊的Hello World。 我们所做的似乎是一个微小的改进,但是我们在我们的 ASP 中使用了控制器和动作方法.NET Core 应用,它给 web 应用开发带来了很多结构和灵活性。
下面是运行应用时所发生的步骤序列:
- 应用在 URL
http://localhost:50140
上运行,其中50140
是 IIS Express 为在本地系统上运行应用而选择的端口号。 这个数字可能有所不同。 - 因为我们没有传递任何参数,所以将选择
Controller
和action
方法的默认值。 在我们的案例中,HomeController
将被选择为Controller
,Index
将被选择为HomeController
中的action
方法。 因为ID
是可选值,并且它没有被传递,所以这个ID
参数被忽略。 - 路由引擎选择
Controller
和action
方法后,将控制传递给所选控制器的action
方法。 在我们的例子中,它将是HomeController
的Index
动作方法。 - 在
Index
操作方法中,我们返回一个字符串Hello World! I am learning ASP.Net MVC 6!
。 此文本从控制器返回,然后控制器返回给用户。
IActionResult
如果您注意到,控制器的action
方法的默认返回类型是IActionResult
,然后我们将返回类型更改为字符串,以便返回文本Hello World...
。
IActionResult
是我们可以用来返回从简单字符串到复杂 JSON 数据的不同类型ActionResult
的接口,因此,我们不需要更改action
方法的return
类型来返回字符串。
在前面的示例中,为了简化操作,我将return
类型更改为字符串。 现在,让我们做一个简单的更改,通过保持返回类型(IActionResult
)不变来返回字符串:
// GET: /<controller>/
public IActionResult Index() {
return Content("Hello World! I am learning MVC 6!");
}
在返回字符串时,我们使用的是前面的action
方法中的Controller
类(继承HomeController
的基控制器)中的virtual
方法,称为Content
。 这个Content()
方法的目的是将字符串转换为IActionResult
类型。
现在,运行应用。 我们应该得到同样的结果。
IActionResult
能够返回不同的数据类型:
ContentResult
:可以返回文本结果。EmptyResult
:返回null
结果。FileResult
:返回二进制输出以写入响应。HttpStatusCodeResult
:提供返回方式。JavaScriptResult
:返回一个可以从客户端执行的脚本。JSonResult
:返回序列化的 JSON 对象。RedirectResult
:重定向到另一个action
方法。RedirectToRouteResult
:表示使用指定路由值字典执行重定向的结果。
添加视图
我们从控制器返回一个简单的字符串。 虽然这解释了Controller
和action
方法如何工作的概念,但它没有太多实际用途。
让我们创建一个名为Index2
的新方法action
:
public IActionResult Index2() {
return View(); // View for this 'Index2' action method
}
现在,我们已经创建了返回 View 的action
方法。 但我们仍然没有添加视图。 按照惯例,ASP.NET MVC 会尝试在文件夹Views\{ControllerName}\{ActionMethod.cshtml}
中搜索我们的视图。 对于前面的例子,它将尝试搜索Views\Home\Index2.cshtml
。 请注意,controller
文件夹的名称是Home
,而不是HomeController
。 根据约定,只有前缀是需要的。 由于此文件夹结构和文件不可用,当您试图通过 URLhttp://localhost:50140/Home/Index2
访问此操作方法时,您将得到一个500 内部服务器错误。
因此,让我们创建一个文件夹结构。 右键单击解决方案,从上下文菜单中选择Add|New Folder,创建一个名为Views
的文件夹,然后在Views
文件夹中创建名为Home
的子文件夹:
右击Home
文件夹,并从上下文菜单中选择添加|新建项目。 将出现如下截图所示的对话框。 将文件命名为Index2.cshtml
,因为我们的action
方法名为Index2
。 cshtml
是使用 c#时使用的剃刀视图引擎(这将在Views章节的ViewEngines部分详细讨论)扩展。
点击前面屏幕上的Add按钮,将创建一个名为Index2.cshtml
的文件,其内容如下:
@*
是 razor 视图引擎中的注释语法。 你可以在@{}
块中编写任何 c#代码。
让我们在生成的代码后面添加一个简单的 HTML 块:
<html>
<body>
Hello! This is <b>my first View</b>
</body>
</html>
现在,当你运行应用时,你会得到以下输出:
下面的图表解释了请求流以及我们如何通过视图生成响应:
添加模型
模型表示您的业务领域类。 现在,我们将学习如何在控制器中使用模型。 创建一个Models
文件夹并添加一个简单的Employee
类。 这只是一个普通的老 c#类:
public class Employee {
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Designation { get; set; }
}
在我们的HomeController
中创建一个新的action
方法Employee
,并使用一些值创建Employee
模型的一个对象,并将模型传递给视图。 我们的想法是在视图中使用模型员工价值观来呈现给用户:
using Chapter3.Models;
public IActionResult Employee() {
//Sample Model - Usually this comes from database
Employee emp1 = new Employee {
EmployeeId = 1,
Name = "Jon Skeet",
Designation = " Software Architect"
};
return View(emp1);
}
现在,我们需要为这个action
方法添加相应的视图。 在View\Home folder
中添加一个新的 Razor 视图文件。
添加以下代码片段。 在@
符号之后的任何东西都被认为是剃刀代码。 在下面的代码中,我们试图访问传递给视图的Model
对象的属性。 在本例中,Model
表示在action
方法中构造的employee
对象。 你可以使用 Model 关键字从 View 中访问对象:
<html>
<body>
Employee Name : @Model.Name <br/>
Employee Designation: @Model.Designation <br/>
</body>
</html>
当您运行应用并输入 URLhttp://localhost:50140/Home/Employee
时,您将看到以下输出:
从控制器传递数据到视图
我们刚刚讨论了如何使用Model
对象将数据从控制器传递到视图。 在调用 View 时,我们将模型数据作为参数传递。 但有时你需要从控制器向视图传递一些临时数据。 这个临时数据可能不值得使用model
类。 在这种情况下,我们可以使用ViewBag
或ViewData
。
ViewData
是字典,ViewBag
是同一值的动态表示。
让我们使用ViewBag
和ViewData
添加公司名称和公司位置属性,如下代码片段所示:
public IActionResult Employee() {
//Sample Model - Usually this comes from database
Employee emp1 = new Employee {
EmployeeId = 1,
Name = "Jon Skeet",
Designation = " Software Architect"
};
ViewBag.Company = "Google Inc";
ViewData["CompanyLocation"] = "United States";
return View(emp1);
}
在 View 文件中做相应的更改,这样我们就可以显示Company
name 和Company location
值:
<html>
<body>
Employee Name : @Model.Name <br/>
Employee Designation: @Model.Designation <br/>
Company : @ViewBag.Company <br/>
Company Location: @ViewData["CompanyLocation"] <br />
</body>
</html>
在进行上述更改后,运行应用:
ViewBag
和ViewData
表示同一个集合,尽管集合中的条目是通过不同的方法访问的。 ViewBag
值是动态值,在运行时执行,而ViewData
是通过字典访问的。
为了测试这一点,让我们对我们的view
文件做一个简单的更改:
Employee Name : @Model.Name <br/>
Employee Designation: @Model.Designation <br/>
Company : @ViewData["Company"] <br />
Company Location : @ViewBag.CompanyLocation <br />
尽管我已经使用ViewBag
将Company
值存储在Controller
中,但我正在使用ViewData
访问相同的值。 对于Company Location
值也是如此,我们使用ViewData
将值存储在 Controller 中,但是我们使用ViewBag
访问该值。
在进行上述更改后运行应用时,您将看到与前面相同的结果。
过滤器
过滤器在 ASP.NET MVC 使您能够在执行管道中的特定阶段之前或之后运行代码。 它们可以针对每个控制器或每个操作进行全局配置。
有不同种类的过滤器,并且每个过滤器在管道中的不同阶段执行。 例如,在执行action
方法时执行动作筛选器。
让我们用一个简单的例子来看看动作过滤器(一种过滤器)是如何工作的。
我已经创建了一个简单的控制器DateController
,我只是在其中显示时间。 在这个action
方法中,我使用了一个名为ResponseCache
的预定义操作过滤器,它将响应缓存到以秒为单位指定的持续时间内。 在下面的代码片段中,我们提到了持续时间为 600 秒。 因此,响应将被缓存 10 分钟。
public class DateController : Controller {
[ResponseCache(Duration = 600)]
public IActionResult Index() {
return Content(DateTime.Now.ToShortTimeString());
}
}
当我第一次运行它时,它显示预期的时间。 但是当您刷新浏览器(它间接地再次触发请求)时,时间不会更新,因为响应已经被应用缓存了。 在下面的截图中,即使时间是 7:43,应用仍然显示为 7:40:
以下是 ASP 中可用的预定义类型的过滤器。 净的核心。
授权过滤器
它们用于授权,主要用于确定当前用户是否被授权进行请求。
资源过滤器
这些是在授权后处理请求的过滤器,也是在请求离开过滤器管道之前处理请求的最后一个过滤器。 它们用于实现缓存或通过过滤器管道传递。
动作过滤器
这些封装了对单个action
方法调用的调用,并且可以操纵传递到动作中的参数以及从动作返回的动作结果。
异常过滤器
它们用于管理 ASP 中未处理的异常。 净 MVC。
结果过滤器
这封装了单个操作结果,并且它们只在action
方法成功执行时运行。
总结
在本章中,我们构建了我们的第一个 ASP.NET 5 应用从头开始,我们已经安装了 ASP。 在我们的 asp.NET Core。 净 5 应用。 我们已经了解了控制器是如何适应整个 ASP 的.NET MVC 应用,并学习了如何使用action
方法构建您的第一个控制器。 我们还学习了如何在控制器中使用模型和视图。 我们还讨论了使用ViewBag
和ViewData
将数据从控制器传递到视图的不同方法。 我们还学习了 ASP 中的过滤器。 asp.net MVC 中预定义过滤器的使用。 净的核心。
版权属于:月萌API www.moonapi.com,转载请注明出处