APS.NET MVC + EF (05)---控制器
Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务端的交互,并且负责协调Model与View之间数据传递,是ASP.NET MVC框架核心。Controller为ASP.NET MVC框架的核心组成部分,其主要负责处理浏览器请求,并决定响应什么内容给浏览器,但并不负责决定内容应如何显示(View的职责)。
5.1 动作方法
Controller本身就是一个类(Class),该类别有许多方法(Method),这些方法中只要是公开方法(public method)就会被视为是一个动作(Action)或动作方法(Action Method),并可以通过该动作方法接收客户端传来的请求和决定响应的视图(View)。
Controller应具备如下几个基本条件。
(1)Controller必须为公开类别;
(2)Controller名称必须以Controller结尾;
(3)必须继承自ASP.NET MVC内建的Controller类别,或实现IController自定义类别;
(4)动作方法必须为公开方法,任何非公开的方法如声明为private或protected的方法都不会被视为一个动作方法;
5.1.1 同名方法问题
在一般的类中,方法是可以重载的,但是动作方法是不可以重载的。如示例1中代码在编译的时候不会有任何问题,但在运行时就会出现如图5-1所示的错误。
示例1
public class AccountController : Controller { public ActionResult Register() { //省略代码 } public ActionResult Register(User user) { //省略代码 } } |
图5-1 动作方法不明确
上面的错误说明ASP.NET MVC 路由系统不能凭借方法参数去定位动作方法。
5.1.2 动作方法上的特性
解决同名方法的问题一般有3种方法,3种方法都是要在动作方法上应用特性。
- 谓词筛选特性
在ASP.NET MVC中,提供了区分不同请求的请求谓词筛选特性,如HttpGet、
HttpPost、HttpDelete和HttpPut,分别对应Get、Post、Delete和Put几种请求。对于示例1的代码,可以按照示例2的方式应用特性。
示例2
public class AccountController : Controller { [HttpGet] public ActionResult Register() { //省略代码 } [HttpPost] public ActionResult Register(User user) { //省略代码 } } |
示例2的代码表示,Register( ) 方法只能对应到Get方式的请求,Register(User user)方法只能对应到Post方式请求。
- NonAction特性
若控制器某个方法特性为NonAction,即使该Action方法是"公开方法",也不会被被看作Action来运行。
主要用途:
- 保护Controller中的特定公开方法不要发布到Web上;
- 功能尚未开发完成就要进行部署,暂时不想将此方法删除。
示例3
public class HomeController : Controller { public ActionResult Index() { return View(); } [NonAction] public ActionResult Index(int id) { return View(); } } |
- ActionName特性
在ASP.NET MVC中,路由中定义的Action的名称和控制器中定义的动作方法的名称命名通常是一致的,但这只是一般的方法,也可以让Action和动作方法的名称不一致,用法如示例4所示。
示例4
public class HomeController : Controller { public ActionResult Register() { //省略代码 } [ActionName("RegisterUser")] public ActionResult Register(User user) { //省略代码 } } |
示例5中,将Register(User user)方法的Action名声明为RegisterUser,解决了同名冲突问题。使用这种方法,需要注意在视图中提交表单的Action属性也要做相应的修改,如下面的代码。
<form action="/Account/RegisterUser" method="post">
</form>
5.1.3 动作方法的结果类型
在前面的内容中,我们习惯使用ActionResult作为动作方法的返回类型,通过View()方法返回对象。其实View()方法的返回类型是ViewResult,ViewResult和ActionResult的关系图5-2所示。
图5-2 ActionResult类关系图
在动作方法定义中,很显然使用了多态,ActionResult是一个抽象类,返回的对象为子类类型。在实际的开发中,有时候不需要 向客户端输出HTML,而是文件、文本等其它一些输出,这时候子类就派上用场了,常用的输出类型如表5-1所示。
表5-1 常用输出类型
输出类型 |
说 明 |
EmptyResult |
输出空内容 |
ContentResult |
将指定内容作为文本输出 |
JsonResult |
输出JSON字符串 |
JavaScriptResult |
输出JavaScript文件 |
RedirectResult |
指定的 URI 来执行重定向 |
RedirectToRouteResult |
指定路由值来执行重定向 |
FilePathResult |
指定文件路径来输出文件 |
FileContentResult |
指定字节数组来输出文件 |
FileStreamResult |
指定流来输出文件 |
ViewResult |
调用视图文件输出视图 |
在实际使用这些类型时,不需要在动作方法中实例化这些类的实例再返回,再Controller类中,已经定义了返回这些类型实例的方法,直接调用即可。如View()方法。常用的方法如表5-2所示。
表5-2 常用控制器输出方法
类型 |
方 法 |
EmptyResult |
无 |
ContentResult |
Content(string content) |
JsonResult |
Json(object data) |
JavaScriptResult |
JavaScript(string script) |
RedirectResult |
Redirect(string url) |
RedirectToRouteResult |
RedirectToAction(string actionName) |
FilePathResult |
File(string fileName, string contentType) |
FileContentResult |
File(byte[] fileContents, string contentType) |
FileStreamResult |
File(Stream fileStream, string contentType) |
ViewResult |
View(string viewName) |
各种方法的用法如示例5所示。
示例5
public class HomeController : Controller { public ActionResult Index() { return View(); } //页面跳转 public ActionResult RedirectTest() { return Redirect("/Home/Detail"); } //页面跳转 public ActionResult RedirectToRouteTest() { return RedirectToRoute(new { controller = "Home", action = "Detail", id = 1, cate = "test" }); } //页面跳转 public ActionResult RedirectToActionTest() { return RedirectToAction("Detail", new { id = 1, cate = "test" }); } //输出JSON文件 public ActionResult JsonTest() { var book = new { bookid = 1, bookName = "精通ASP.NET MVC", author = "Fangyc", publishData = DateTime.Now }; return Json(book, JsonRequestBehavior.AllowGet); } //输出JavaScript文件 public ActionResult JavaScriptTest() { string js = "alert('Welecome to ASP.NET MVC!')"; return JavaScript(js); } //按文件路径输出文件 public ActionResult FilePathTest() { return File("~/Content/rain.mp3", "audio/mp3"); } //对字符串编码并输出文件 public ActionResult FileContentTest() { string content = "Welcome to ASP.NET MVC!"; byte[] contents = System.Text.Encoding.UTF8.GetBytes(content); return File(contents, "text/plain"); } //用文件流输出文件 public ActionResult FileStreamTest() { string content = "Welcome to ASP.NET MVC!"; byte[] contents = System.Text.Encoding.UTF8.GetBytes(content); FileStream fs = new FileStream( Server.MapPath("~/Content/ASP.NET MVC.pdf"), FileMode.Open); return File(fs, "application/pdf"); } //输出简单文本 public ActionResult ContentTest() { string content = "<h1>Welcome to ASP.NET MVC!</h1>"; return Content(content); } } |
在ASP.NET MVC中,动作方法的返回类型并不一定是ActionResult类型,也可以是其它任何类型,甚至是void类型,如下面的代码。
public int Sum(int num1,int num2) { int sum=num1+num2; return sum; } public void log() { File.WriteAllText(@"D:\log.test", "保存文件"); } |
上述这种返回类型的动作方法称为隐式动作方法,ASP.NET MVC 自动做了一些处理,将void类型对应到EmptyResult类型,将其它非ActionResult类型对应到ContentResult类型。
5.2 动作方法参数
我们以前在动作方法中获取 URL 和表单数据的方法,可能会采用如下方式:
string name=Request.Forms["name"];
string id=RouteData.Values["id"];
除了上面的方法外,ASP.NET MVC 还提供了更加便利的方法。
5.2.1 简单类型映射
在ASP.NET MVC中,可以把路由数据、URL数据、表单数据自动映射到动作方法参数中,这些参数可以直接定义为基本数据类型或string类型。
示例6
public ActionResult Detail() { int id = Request.QueryString["id"] != null? Convert.ToInt32(RouteData.Values["id"]):0; // 省略代码 return View(); } public ActionResult Detail(int id=0) { // 省略代码 } |
示例6中,第二个方法参数使用了数据映射的功能,RouteData.Values["id"]的值可以自动映射到参数id中。
示例7
public ActionResult List() { int pageCount = 0;//总页数 int categoryId = Request.QueryString["categoryId"] != null ? Convert.ToInt32(Request.QueryString["categoryId"]) : 1; //页序号 int pageIndex = Request.QueryString["pageIndex"] != null ? Convert.ToInt32(Request.QueryString["pageIndex"]) : 1; //排序字段 string order = Request.QueryString["order"] != null ? Convert.ToString(Request.QueryString["order"]) : "PublishDate"; BookManager manager = new BookManager(); List<Book> list = manager.GetBooks( categoryId, this.PageSize, pageIndex, ref pageCount, order); } public ActionResult List(int categoryId = 1, int pageIndex = 1, string order = "PublishDate") { int pageCount = 0;//总页数 BookManager manager = new BookManager(); List<Book> list = manager.GetBooks(categoryId, this.PageSize, pageIndex, ref pageCount, order); } |
示例7中,第二个方法参数使用了数据映射的功能,该方法定义了多个参数,各个参数的值都由Request.QueryString映射而来。
示例8
public ActionResult LogIn() { string userName=Request.Form["userName"]; string password=Request.Form["password"]; string returnUrl=Request.Form["returnUrl"]; // 省略代码 } public ActionResult LogIn(string userName, string password, string returnUrl) { // 省略代码 } |
从上述三个示例可以看出,使用动作方法参数自动映射,简化了大量代码。
获取数据的优先级依次是表单数据--->路由数据--->URL数据。在定义动作方法参数时,需要保证以下两点。
- 参数名要和目标数据参数名一致(不区分大小写)。
- 参数数据类型要和来源数据的目标数据类型一致。
对于值类型参数的数据,如果从来源数据获取不到相应的值,就会出现参数映射的运行时错误,一般把这种参数直接声明为可空类型或可选参数。
5.2.2 映射模型
动作方法参数的映射不仅仅是简单类型,还可以是复杂类型。如示例 8所示。
示例8
<form action="/Account/RegisterUser1" class="member_form" id="Form1" method="post"> <p> <label><span>*</span>用户名</label> <input class="opt_input" name="LoginId" type="text"/> 5-12个字符或数字组成,可用中文名 </p> <p> <label><span>*</span>真实姓名</label> <input class="opt_input" name="Name" type="text"/> </p> <p> <label><span>*</span>密 码</label> <input class="opt_input" name="LoginPwd" type="password"/> </p> <p> <label><span>*</span>确认密码</label> <input class="opt_input" name="PasswordConfirm" type="password" /> </p> <p> <label><span>*</span>电子邮件</label> <input class="opt_input" name="Mail" type="text" /> </p> <!-- 省略其它代码 --> </form> // 控制器代码 public ActionResult RegisterUser(User user) { UserManager manager = new UserManager(); if (!manager.Register(user)) { //省略代码 } return View("Register", user); } |
示例8的方法中,并没有创建User对象,也没有给其属性赋值。其实这些工作是ASP.NET MVC通过分析User对象的属性和表单中元素按名称进行匹配并进行赋值。通过这种方式,自动完成对象创建和初始化赋值工作。这也被称为ASP.NET MVC的模型自动绑定功能。
5.3 案例:用户注册(或信息添加)
APS.NET MVC + EF (05)---控制器的更多相关文章
- APS.NET MVC + EF (06)---模型
在实际开发中,模型往往被划分为视图模型和业务模型两部分,视图模型靠近视图,业务模型靠近业务,但是在具体编码上,它们之间并不是隔离的. 6.1 视图模型和业务模型 模型大多数时候都是用来传递数据的.然而 ...
- APS.NET MVC + EF (11)---过滤器
过滤器本质就是对动作方法的执行过程进行干预,这种干预可以影响动作方法执行的各个过程.ASP.NET MVC 提供了4种类型的接口,并在接口中定义了各种成员,代表代码执行的各个阶段,这些接口和成员如表1 ...
- APS.NET MVC + EF (08)---数据注解和验证
对于Web开发人员来说,用户输入验证一直是一个挑战.不仅在客户端浏览器中需要执行验证逻辑,在服务器端也需要执行.如果觉得验证是令人望而生畏的繁杂琐事,ASP.NET MVC框架提供了数据注解的方式帮助 ...
- APS.NET MVC + EF (07)---表单和HTML辅助方法
在ASP.NET MVC中,可以借助HtmlHelper 对象来输出页面内容,提高开发效率.下面,我们将介绍一些常用的辅助方法. 7.1 HTML辅助方法 BeginForm 该辅助方法主要用来产生& ...
- APS.NET MVC + EF (04)---路由和数据传递
4.1 视图引擎 ASP.NET MVC 提供两种视图引擎:ASPX(C#)和Razor(CSHTML),推荐使用Razor. 4.1.1 Razor的语法 在Razor视图中,所有的服务器端代码都是 ...
- APS.NET MVC + EF (03)---初始MVC
3.1 MVC简介 MVC(Model-View-Controller,模型—视图—控制器模式)用于表示一种软件架构模式.它把软件系统分为三个基本部分:模型(Model),视图(View)和控制器(C ...
- APS.NET MVC + EF (14)---项目框架搭建
一:框架搭建 1:先创建Model. 2:创建数据访问接口层.IUserInfoDal 在该接口中定义了常见的方法CURD以及分页方法. public interface IUserInfoD ...
- APS.NET MVC + EF (10)---使用AJAX
在Web系统中,Ajax技术已经成为提高用户体验的必备技术.开发Ajax程序,涉及两方面的内容:一是客户端技术,二是服务器端技术. (1)客户端技术 核心工作是通过JavaScript向服务器发送数据 ...
- APS.NET MVC + EF (02)---深入理解ADO.NET Entity Framework
2.7 深入理解Entity Framework 性能问题几乎是一切ORM框架的通病,对于EF来说,引起性能低的原因主要在以下几个方面. 复杂的对象管理机制为了在.NET中更好地管理模型对象,EF提供 ...
随机推荐
- Linux的httpd服务介绍和部署
软件介绍 客户端代理软件 IE,firefox,chroome,opera 服务器端软件 httpd,Nginx,Tengine,ISS,Lighthttp 应 ...
- Linux服务管理之ntp
NTP是网络时间协议(Network Time Protocol),它是用来同步网络中各个计算机的时间的协议. 在计算机的世界里,时间非常地重要,例如对于火箭发射这种科研活动,对时间的统一性和准确性要 ...
- Html快速上手
Html 概述 HTML文档 Doctype Meta Title Link Style Script 常用标签 各种符号 p 和 br a 标签 H 标签 select input:checkbox ...
- rollup入门
作为js程序员,掌握rollup是必要的. 有了webpack后,为什么还要用rollup, 因为webpack不专业,webpack是打包一切. rollup只为打包js而生. rollup通过的五 ...
- 在spring boot中三分钟上手apache顶级分布式链路追踪系统skywalking
原文:https://juejin.im/post/5cd10e81e51d453b560f2d53 skywalking在apache里全票通过成为了apache顶级链路追踪系统 项目地址:gith ...
- vue中axios的简单使用
我们一般在用jq的时候会使用到ajax来进行与服务器之间的交流,vue中也提供了相应的类似于ajax的方法-axios来进行与服务器之间的数据传递 现在的这篇是最简单的使用,后续会添加上来复杂的使用 ...
- 通过async实现协程的延迟执行及结果获取
在上一次https://www.cnblogs.com/webor2006/p/12022065.html对于协程的async和wait进行了初步的学习,其可以加速执行的性能,其实对于async它是提 ...
- opencv 程序
IplImage结构中的一个元素:struct _IplROI *roi; //图像感兴趣区域,当该值非空时,只对该区域进行处理 . ROI :Region of Interest,表示感兴趣的区 ...
- 201671030113 李星宇 实验十四 团队项目评审&课程学习总结
项目 内容 所属课程 [所属课程(https://www.cnblogs.com/nwnu-daizh/) 作业要求 作业要求 课程学习目标 (1)掌握软件项目评审会流程:(2)反思总结课程学习内容 ...
- css 布局 一中一右
.container { position: relative; .my-center { text-align: center; line-height: 30rpx; min-width: 400 ...