10.5 理解控制器
学习目标
了解控制器的作用,掌握控制器、自定义动作的创建。
10.5.1 控制器作用
控制器负责用户与MVC应用程序交互的方式。当用户发出浏览器请求时,控制器决定向用户发回什么样的响应。
控制器不过是一个类(例如,一个Visual Basic或者C#类)。上一节列举的ASP.NET MVC应用程序例子中包含一个名为HomeController.cs的控制器,它位于Controllers文件夹下。HomeController.cs源代码如下。
public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "修改此模板以快速启动你的ASP.NET MVC 应用程序。"; return View(); } public ActionResult About() { ViewBag.Message = "你的应用程序说明页。"; return View(); } public ActionResult Contact() { ViewBag.Message = "你的联系方式页。"; return View(); } }
注意到HomeController拥有3个方法,名为Index、About和Contact。这3个方法对应于控制器对外提供了3个动作。其中/Home/Index将会调用HomeController.Index()方法,而URL /Home/About会调用HomeController.About()方法,而URL /Home/Contact会调用HomeController.Contact()方法。
控制器中的任何公共方法都对外提供了一个控制器动作。这就意味着只要通过在浏览器中输入正确的URL,就可以访问包含在控制器中的任何公共方法。
10.5.2 控制器动作结果
控制器动作返回一种叫作动作结果(Action Result)的东西。动作结果是控制器动作返回给浏览器请求的东西。
ASP.NET MVC框架支持6种标准类型的动作结果。
(1)ViewResult:HTML及标记。
(2)EmptyResult:无结果。
(3)RedirectResult:重定向到一个新的URL。
(4)RedirectToRouteResult:重定向到一个新的控制器动作。
(5)JsonResult:一个JSON结果,它可以用于Ajax应用程序。
(6)ContentResult:文本结果。
所有这些动作结果都继承自ActionResult基类,故,系统默认生成的所有动作都返回一个ActionResult类型,其实可以写成具体的类型。
在大多数情况下,控制器动作返回的类型都是ViewResult。例如,下面的代码中的HomeController控制器中的Index动作就返回了一个ViewResult。
public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "修改此模板以快速启动你的ASP.NET MVC 应用程序。"; return View(); } }
当一个动作返回一个ViewResult时,将会向浏览器返回HTML。上面代码中的Index()方法向浏览器返回一个名为Index.aspx的视图。
其实,Index()动作并没有返回一个ViewResult。而是调用了Controller基类的View()方法(return View();)。通常情况下,并不直接返回一个动作结果。而是调用Controller基类的下列方法之一。
(1)View:返回一个ViewResult结果。
(2)Redirect:返回一个RedirectResult动作结果。
(3)RedirectToAction:返回一个RedirectToAction动作结果。
(4)RedirectToRoute:返回一个RedirectToRoute动作结果。
(5)Json:返回一个JsonResult动作结果。
(6)Content:返回一个ContentResult动作结果。
因此,如果要向浏览器返回一个视图,通常都是调用View()方法。如果要让用户从一个控制器动作重定向到另一个控制器,可以调用RedirectToAction()方法。
例如,下面的代码Details()动作要么显示一个视图,要么将用户重定向到Index()动作,取决于Id参数是否含有值。
其中“int? Id”的意思就是可以给Id传值,也可以不传值,都不会报错的,这种新式的参数称为可空参数(可以拥有Null值),URL可以写成:/Home/Details/3访问,也可以写成:/Home/Details访问,按照下面的代码,/Home/Details/3就会访问Details视图并传递Id=3,而/Home/Details就直接访问Index视图了。
如果写成“int Id”的意思就是必须给Id传值,否则就会报错,URL只能写成:/Home/Details/3访问,而不能写成:/Home/Details访问,按照下面的代码,/Home/Details/3就会访问Details视图并传递Id=3,而/Home/Details访问服务器会报错,提示访问的地址不存在。
public ActionResult Details(int? Id) { if (Id == null) return RedirectToAction("Index"); return View(); }
ContentResult动作结果很特别。可以使用ContentResult动作结果来将动作结果作为纯文本返回。例如,下面的代码Hello()动作将消息作为纯文本返回,而不是HTML,如果直接访问/Home/Hello,就和视图Views没有关系了,浏览器显示如图10-13所示。
public ContentResult Hello() { return Content("Hello world!"); }
图10-13 访问/Home/Hello浏览器显示结果
如果一个控制器动作返回了一个结果,而这个结果并非一个动作结果,如一个日期或者整数,那么结果将自动被包装在ContentResult中。例如,下面的代码是HomeController的Today()动作时,日期将自动作为一个ContentResult返回,访问/Home/Today,浏览器显示如图10-14所示。
public DateTime Today() { return DateTime.Now; }
图10-14 访问/Home/Today浏览器显示结果
10.5.3 创建控制器
在ASP.NET MVC 4 Web应用程序中创建一个新控制器Controller的最简单方法是在Visual Studio 2012的解决方案资源管理器的Controllers文件夹上右击,然后在弹出的快捷菜单中选择“添加”|“控制器”,如图10-15所示。弹出“添加控制器”对话框,如图10-16所示。
图10-15 添加控制器菜单选项
图10-16 “添加控制器”对话框
在图10-16中,控制器名称的第一部分在“添加控制器”对话框中高亮显示了。每一个控制器的名称必须以Controller后缀结尾。例如,可以创建一个叫作ProductController的控制器,但是不能创建一个叫作Product的控制器。再者,一定在Controllers文件夹中创建控制器,否则的话,就破坏了ASP.NET MVC的惯例。这几乎已经是MVC 4应用程序的不成文的规定。
在图10-16中的“控制器名称”文本框中输入ProductController,然后单击“添加”按钮,就完成了一个ProductController控制器的创建,系统同时打开这个控制器,默认该控制器源代码如下。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MvcApplication1.Controllers { public class ProductController : Controller { // // GET: /Product/ public ActionResult Index() { return View(); } } }
可以看出,系统默认只是给ProductController增加了一个默认的Index动作。当然、此时,该控制器还没有视图,可以在Index()方法体内右击,在弹出的快捷菜单中选择“添加视图”就可以进入“添加视图”对话框,这个在后面再详细讲解。
10.5.4 创建自定义动作
默认创建的控制器系统只会添加一个Index方法,通常根据项目功能需要,需要添加一些新的方法到控制器中。
添加新的动作和类中定义新的方法基本类似。例如,下面的代码为控制器定义了一个SayHello()的动作。
public string SayHello() { return "Hello!";}
为了把控制器中的方法作为一个动作公布出去,让用户可以通过URL来访问,方法必须满足如下的要求。
(1)方法必须是公共的。
(2)方法不能是静态方法。
(3)方法不能是扩展方法。
(4)方法不能是构造函数,访问器,或者设置器。
(5)方法不能拥有开放泛型类型(open generic types)。
(6)方法不能是控制器基类中的方法。
(7)方法不能含有ref或者out参数。
10.5.5 阻止公共方法被调用
如果需要在控制器中创建一个公共方法,但是又不想将这个方法发布为控制器公共动作(就是可以通过对应的URL访问),则可以通过使用[NonAction]特性来阻止该方法被外界URL调用。例如,下面的代码就是为控制器定义了一个叫作CompanySecrets()的公共方法,它使用[NonAction]特性进行了修饰,故不能通过外部的URL访问。
public class HomeController : Controller { [NonAction] public string CompanySecrets() { return "This information is secret."; } }
如果在浏览器地址栏输入/Home/CompanySecrets来调用CompanySecrets()控制器动作,客户端浏览器就会报错,如图10-17所示。
图10-17 访问/Home/CompanySecrets显示的错误信息窗口
共有条评论 网友评论