原文:
ASP.NET Core 入门教程 4、ASP.NET Core MVC控制器入门
软件/环境 | 说明 |
---|---|
操作系统 | Windows 10 |
SDK | 2.1.401 |
ASP.NET Core | 2.1.3 |
IDE | Visual Studio Code 1.27 |
浏览器 | Chrome 69 |
本篇代码以下代码进行调整:https://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-02
你可能需要的前置知识
https://baike.baidu.com/item/mvc
在MVC Web框架中,路由模块会对接收到的请求进行匹配并转交由对应的控制器(Controller)进行处理。
控制器的作用就是处理接收到的请求,解析用户输入并执行对应程序理逻辑,然后返回对应的输出。
用户的输入可以是QueryString、FormData、也可以是HTTP Header、HTTP Body。
控制器的输出格式通常是:HTML、JSON、XML、普通文本
所有Controller类都必须直接或间接继承于Microsoft.AspNetCore.Mvc.ControllerBase
。为了搭配视图引擎使用,ASP.NET Core MVC 框架内置了 Microsoft.AspNetCore.Mvc.Controller
类,提供了一些视图引擎需要的特性。所以,默认我们继承该类即可。
Controller类的类名(ClassName)推荐以Controller
为结尾(不区分大小写)。
例如:
路由模块去掉结尾的Controller作为ControllerName。
那么对应的ControllerName
则分别是Home
、Test
。这也是路由映射到Controller的主要标识。
当然,你也可以不以Controller作为控制器类名(ClassName)的固定后缀,那么路由模块会以完整的类名(ClassName)作为ControllerName
在 ASP.NET MVC框架中,控制器(Controller)类名必须以Controller作为后缀,但是在 ASP.NET Core MVC框架中去掉了这个限制。
以下Controller的定义都是可以的:
//推荐 public class HomeController : Controller { //ControllerName=Home } public class HomeController : BaseController { //ControllerName=Home } public class Test : Controller { //ControllerName=Test }
控制器(Controller)操作(Action)就是控制器接收到请求后实际用与处理请求的程序方法/函数。
Controller接收到请求后根据路由的ActionName找到对应的Action,然后将用户的输入映射到该Action的参数,最终Action实际执行完成后再返回对应的输出。
Action必须是控制器中定义的公有非静态方法,例如:
public class HomeController : Controller { public IActionResult Index() { return Content("Hello World ! -ken.io"); } public string Test() { return "test"; } public void DoSomething() { //DoSomething } }
按照默认的路由配置:
如果你在Controller定义了一个公有的非静态方法,但不想让这个方法处理请求,那么可以标记为NonAction
public class HomeController : Controller { [NonAction] public void LogicMethod(){ } }
ASP.NET Core MVC 限定 Action返回类型必须是实现了Microsoft.AspNetCore.Mvc.IActionResult
接口的类型,框架本身提供了该接口的默认实现Microsoft.AspNetCore.Mvc.ActionResult
,并提供了ActionResult类的子类,用于输出不同内容格式的需求。
不过在定义Action方法的时候,返回值类型也可以定义成string、int等,这些自定义的返回类型会在返回到响应流之前被框架自动包装到合适的ActionResult子类型中。
常用的ActionResult子类说明
Action返回类型 | Controller内置方法 | 说明 |
---|---|---|
ViewResult | View() | 将视图数据交由Razor视图引擎渲染 |
PartialViewResult | PartialView() | 将视图数据交由Razor视图引擎部分视图(PartialView)渲染 |
ContentResult | Content() | 返回自定义文本 |
JsonResult | Json() | 返回对象的JSON序列化结果 |
FileResult | File() | 返回要写入响应中的二进制输出 |
RedirectResult | Redirect() | 重定向到指定的Url |
RedirectToRouteResult | RedirectToAction(),RedirectToRoute() | 重定向到指定的Action或者路由 |
EmptyResult | / | 在Action返回null或者Action定义返回关键字是void时会被包装为EmptyResult |
在Controllers文件夹中新建ActionResultTestController.cs
并继承于Controller类用于测试。
using System; using Microsoft.AspNetCore.Mvc; namespace Ken.Tutorial.Web.Controllers { public class ActionResultTestController : Controller { } }
在Startup.cs配置该测试控制器专用路由
//配置ActionResult测试专用路由 routes.MapRoute( name: "ActionResultTest", template: "art/{action}", defaults: new { controller = "ActionResultTest"} );
定义返回ContentResult的Action
public IActionResult ContentTest() { return Content("Content Result Test --ken.io"); }
启动项目,浏览器访问 {host:port}/art/contenttest,将看到以下输出:
ContentResult Test by ken.io
定义返回JsonResult的Action
public IActionResult JsonTest() { return Json(new { Message = "JsonResult Test", Author = "ken.io" }); }
启动项目,浏览器访问 {host:port}/art/jsontest,将看到以下输出
{ "message": "JsonResult Test", "author": "ken.io" }
定义返回FileResult的Action
public IActionResult FileTest() { var bytes = Encoding.Default.GetBytes("FileResult Test by ken.io"); return File(bytes, "application/text", "filetest.txt"); }
启动项目,浏览器访问 {host:port}/art/jsontest,将会下载文件filetest.txt。
文件内容为:
FileResult Test by ken.io
定义返回Redirect相关的Action
public IActionResult RedirectTest() { return Redirect("https://ken.io"); } public IActionResult RedirectToActionTest() { return RedirectToAction("jsontest"); } public IActionResult RedirectToRouteTest() { return RedirectToRoute("Default", new { Controller = "home", Action = "index" }); }
启动项目,浏览器访问测试:
路由将请求交由对应的Controller处理时,Controller会找到对应的Action方法,并从RouteData或HTTP请求数据(QueryString、FormData、Header等)找到执行该方法所需要的参数的值。
如果未找到参数对应的数据,且该参数类型是可以为null的类型,则null将作为参数值传递递,否则将会引发一场。
另外,Action方法也可以不定义参数,手动从RouteData或HTTP请求数据(QueryString、FormData、Header等)获取对应的参数值。
在Controllers文件夹中新建ParamsMappingTestController.cs
并继承于Controller类用于测试。
using System; using Microsoft.AspNetCore.Mvc; namespace Ken.Tutorial.Web.Controllers { public class ParamsMappingTestController:Controller { } }
在Startup.cs配置该测试控制器专用路由
//配置参数映射测试专用路由 routes.MapRoute( name: "ParamsMappingTest", template: "pmt/{action}/{id?}", defaults: new { controller = "ParamsMappingTest"} );
定义接收路由参数的Action
public IActionResult GetId(int id) { return Content($"Action params mapping test by ken.io, id:{id}"); }
启动应用,浏览器访问 /pmt/getid/1024 或者 /pmt/getid?id=1024,将会看到以下输出:
Action params mapping test by ken.io, id:1024
或者通过PostMan等工具post访问 /pmt/getid 在HTTP Header参数增加id=1024并发送请求,也会看到同样输出
定义接收数组参数的Action
public IActionResult GetArray(string[] id) { var message = "Action params mapping test by ken.io,id:"; if (id != null) { message += string.Join(",", id); } return Content(message); }
应用启动,浏览器访问 /pmt/getarray/1,2 或者 /pmt/getarray?id=1,2,将会看到以下输出:
Action params mapping test by ken.io,id:1,2
或者通过PostMan等工具post访问 /pmt/getarray 并设置表单参数并发送请求,也会看到同样输出
在项目根目录创建Models文件夹,并创建Person.cs类文件
public class Person { public string Name { get; set; } public int Age { get; set; } }
定义接收自定义参数的Action
public IActionResult GetPerson(Person person) { return Json(new { Message = "Action params mapping test by ken.io", Data = person }); }
应用启动,浏览器访问 /pmt/getperson?name=ken&age=18,将会看到以下输出:
{ "message": "Action params mapping test by ken.io", "data": { "name": "ken", "age": 18 } }
或者通过PostMan等工具post访问 /pmt/getperson 并设置表单参数并发送请求,也会看到同样输出
定义接收自定义类型数组参数的Action
public IActionResult GetPersonList(List<Person> person) { return Json(new { Message = "Action params mapping test by ken.io", Data = person }); }
启动应用,浏览器访问 /pmt/getpersonlist?person[0].name=ken&person[0].age=18&person[1].name=tom&person[1].age=20
将会看到以下输出:
{ "message": "Action params mapping test by ken.io", "data": [ { "name": "ken", "age": 18 }, { "name": "tom", "age": 20 } ] }
或者通过PostMan等工具post访问 /pmt/getpersonlist 并设置表单参数并发送请求,也会看到同样输出
定义接收JSON类型参数的Action
public IActionResult GetPersonJson([FromBody]Person person) { return Json(new { Message = "Action params mapping test by ken.io", Data = person }); }
启动应用,这时候我们就只能通过PostMan工具进行测试了
首先设置 Content-Type=application/json
然后设置JSON表单参数并发送请求,就会看到对应输出
定义手动获取参数的Action
public IActionResult GetByHand() { return Json(new { Id = RouteData.Values["id"], Name = Request.Query["name"] }); }
应用启动后,浏览器访问 /pmt/getbyhand/1024?name=ken&name=tom&age=18
将看到以下输出:
{ "id": "1024", "name": [ "ken", "tom" ] }
RouteData.Values[“id”]:从路由数据中获取数据
Request.Query[“name”]:从Url参数中获取数据
Request.Form[“name”]:从表单参数中获取数据
https://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-04
本文首发于我的独立博客:https://ken.io/note/asp.net-core-tutorial-mvc-controller-action