ASP.NET MVC 应用程序中的控制器
ASP.NET MVC 框架可将 URL 映射到称为“controller”的类。 控制器将处理传入的请求,处理用户输入和交互,并执行相应的应用程序逻辑。 Controller 类通常会调用单独的视图组件以为请求生成 HTML 标记。
适用于所有控制器的基类为 ControllerBase 类,该类可进行普通的 MVC 处理。 Controller 类从 ControllerBase 中继承并且是控制器的默认实现。 Controller 类负责以下处理阶段的工作:
查找要调用的相应操作方法,并验证是否可以调用该方法。
获取要用作操作方法的参数的值。
处理在执行操作方法期间可能发生的所有错误。
提供用于呈现 ASP.NET 页面类型(视图)的默认 WebFormViewEngine 类。
所有 controller 类都必须使用“Controller”后缀来命名。 下面的示例演示了名为 HomeController 的 controller 类的示例。 此 controller 类包含呈现视图页的操作方法。
[HandleError] public class HomeController : Controller { public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; return View(); } public ActionResult About() { return View(); } }
操作方法
在未使用 MVC 框架的 ASP.NET 应用程序中,用户交互通常围绕以下方面来组织:页面、由页面和页面控件引发的事件,以及处理页面和页面控件引发的事件。 相比之下,在 ASP.NET MVC 应用程序中,用户交互围绕控制器和操作方法进行组织。 控制器定义操作方法。 控制器可根据需要包括多个操作方法。
操作方法与用户交互之间通常具有一对一映射关系。 例如,用户交互包括将 URL 输入到浏览器中、单击链接以及提交表单。 这些用户交互中的每一项都会将请求发送给服务器。 在每种情况下,请求的 URL 均包含 MVC 框架用于调用操作方法的信息。
当用户将 URL 输入到浏览器中时,MVC 应用程序会使用 Global.asax 文件中定义的路由规则来分析 URL 并确定控制器的路径。 然后,该控制器会确定合适的操作方法来处理请求。 默认情况下,请求的 URL 被视为一个子路径,该子路径包含后面跟有操作名称的控制器名称。 例如,如果用户输入 URL http://contoso.com/MyWebSite/Products/Categories,则子路径为 /Products/Categories。 默认路由规则将"Products"视为控制器的前缀名称 (如 ProductsController) 它将"Categories"视为操作的名称。 因此,该路由规则将调用 Products 控制器的 Categories 方法来处理请求。 如果 URL 以 /Products/Detail/5 结尾,则默认的路由规则将“Detail”视为操作的名称,并且调用 Products 控制器的 Detail 方法来处理请求。 默认情况下,此 URL 中的值“5”将作为参数传递给 Detail 方法。
下面的示例演示了一个具有 HelloWorld 操作方法的控制器类。
public class MyController : Controller { public ActionResult HelloWorld() { ViewData["Message"] = "Hello World!"; return View(); } }
ActionResult 返回类型
大多数操作方法会返回从ActionResult 中派生的类的实例。ActionResult 类是所有操作结果的基础。不过,也存在不同的操作结果类型,具体取决于操作方法执行的任务。例如,最常见的操作是调用 View 方法。View 方法返回从 ActionResult 中派生的ViewResult 类的实例。
我们也可以创建返回任意类型(如字符串、整数或布尔值)的对象的操作方法。这些返回类型在呈现到响应流之前包装在合适的 ActionResult 类型中。
下表显示了内置操作结果类型以及返回这些类型的操作帮助器方法。
说明 | 操作结果 | 帮助器方法 |
---|---|---|
ViewResult | View | 将视图呈现为网页。 |
PartialViewResult | PartialView | 呈现分部视图,该分部视图定义可呈现在另一视图内的某视图的一部分。 |
RedirectResult | Redirect | 使用其 URL 重定向到另一操作方法。 |
RedirectToRouteResult | RedirectToAction、RedirectToRoute | 重定向到另一操作方法。 |
ContentResult | Content | 返回用户定义的内容类型。 |
JsonResult | Json | 返回序列化的 JSON 对象。 |
JavaScriptResult | JavaScript | 返回可在客户端上执行的脚本。 |
FileResult | File | 返回要写入响应中的二进制输出。 |
EmptyResult | (无) | 表示在操作方法必须返回 null 结果 (void) 的情况下所使用的返回值。 |
将公共方法标记为非操作方法
默认情况下,MVC 框架将 controller 类的所有公共方法都视为操作方法。 如果您的 controller 类包含公共方法,并且您不希望它成为操作方法,则必须用 NonActionAttribute 特性标记该方法。
下面的示例演示用 NonAction 特性标记的方法。
[NonAction] private void DoSomething() { // Method logic. }
操作方法参数
默认情况下,操作方法参数的值是从请求的数据收集中检索到的。 数据收集包括窗体数据名称-数值对、查询字符串值和 cookie 值。
Controller 类将查找操作方法并根据 RouteData 实例和窗体数据确定该操作方法的所有参数值。 如果无法分析参数值,并且参数类型为引用类型或可以为 null 值的类型,则 null 将作为参数值传递。 否则会引发异常。
可以采用多种方法访问 controller 类操作方法中的 URL 参数值。 Controller 类将公开可在操作方法中访问的 Request 和 Response 属性。 这些属性与已为 ASP.NET 的一部分的 HttpRequest 和 HttpResponse 对象具有相同的语义。 但是,Controller 类的 Request 和 Response 对象将接受实现 HttpRequestBase 和 HttpResponseBase 抽象类(而不是成为密封类)的对象。 通过使用这些基类,可以轻松地创建 mock 对象,这样,又可以轻松地为 controller 类创建单元测试。
下面的示例演示如何使用 Request 对象检索名为 id 的查询字符串值。
public void Detail() { int id = Convert.ToInt32(Request["id"]); }
自动映射操作方法参数
ASP.NET MVC 框架可以将 URL 参数值自动映射到操作方法的参数值。 默认情况下,如果操作方法采用参数,则 MVC 框架将检查传入的请求数据并确定该请求是否包含同名的 HTTP 请求值。 如果包含,则该请求值将自动传递给操作方法。
下面的示例演示上面示例的变体。 在此变体中,假定 id 参数映射到名称也为 id 的请求值。 由于此自动映射的缘故,操作方法不必包括用于从请求中获取参数值的代码,因此,参数值更易于使用。
public ResultAction Detail(int id) { ViewData["DetailInfo"] = id; return View(); }
我们也可以将参数值作为 URL 的一部分而不是作为查询字符串值嵌入。 例如,您可以使用 /Products/Detail/3 之类的 URL,而不是使用包含查询字符串的 URL,如 /Products/Detail?id=3。 默认路由映射规则的格式为 /{controller}/{action}/{id}。 如果 URL 中控制器和操作名称后面存在 URL 子路径,则会将该子路径视为名为 id 的参数,并自动将其作为参数值传递给操作方法。
MVC 框架还支持操作方法的可选参数。 MVC 框架中的可选形参是使用控制器操作方法的可以为 null 类型的实参处理的。 例如,如果方法可以采用日期作为查询字符串的一部分,但是您希望在缺少查询字符串参数的情况下默认值为当天日期,则可以使用与以下示例中的代码相似的代码:
public ActionResult ShowArticles(DateTime? date) { if(!date.HasValue) { date = DateTime.Now; } // ... }
如果请求包括日期参数的值,则该值将传递给 ShowArticles 方法。 如果请求不包含此形参的值,则实参为 null,并且控制器可以采用所需的任何操作以处理缺少的形参。