原文链接:http://www.asp.net/learn/mvc/

这篇教程探索了ASP.NET MVC控制器(controller)、控制器动作(controller action)和动作结果(action results)这几个主题。在读完本篇教程之后,你将会理解控制器如何控制访问者与ASP.NET MVC网站进行交互的方式。

1.理解控制器

MVC控制器负责响应对ASP.NET MVC网站发起的请求。每一个浏览器请求都映射到了一个专门的控制器。举个例子,设想一下你在浏览器地址栏输入了下面的URL:

http://localhost/product/index/3

在这种情况下,将会调用一个名为ProductController的控制器。ProductController负责生成对浏览器请求的响应。举个例子,控制器可能会返回一个特定的视图,或者是将用户重定向到另一个控制器。

你可以通过在ASP.NET MVC应用程序的Controllers文件夹下添加一个新的控制器来创建一个新控制器。右键点击控制器的文件夹,并且选择菜单项“Add(添加)”,“New(新建项)”,并选择“MVC Controller Class(MVC控制器类)”(见图1)。控制器的名字必须含有Controller后缀。举个例子,控制器名称ProductController没什么问题,但是控制器Product就不起作用。

图1 – 创建一个新的控制器

如果你创建一个新的名为ProductController的控制器,那么你将会获得代码清单1所示的文件。

代码清单1 – ProductController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApp.Controllers
{
     public class ProductController : Controller
     {
          public ActionResult Index()
          {
               // Add action logic here
               throw new NotImplementedException();
          }
     }
}

如同你在代码清单1中所看到的,控制器不过是一个类(Visual Basic.Net 或者是C#类)。一个控制器是一个继承自System.Web.Mvc.Controller基类的类。因为控制器继承自这个基类,所以控制器轻松地继承了一些有用的方法(我们不久将会讨论这些方法)。

2. 理解控制器动作

控制器暴露出控制器动作。动作是控制器的一个方法,当你在浏览器地址栏输入某一特定的URL时,将会调用这个方法。举个例子,假设你对下面这个URL发出请求:

http://localhost/Product/Index/3

在本例中,Index()方法在ProductController类上被调用。Index()方法是控制器动作的一个例子。

一个控制器动作必须是控制器类的一个公共方法。C#方法,默认时,是私有方法。意识到你添加到控制器类中的任何公共方法都会自动被暴露为控制器动作(你必须非常小心,因为控制器动作可以被全球的任何人调用,仅仅简单地通过在浏览器地址栏输入正确的URL)。

控制器动作还要满足一些额外的需求。作为控制器动作来使用的方法不能够重载。另外,控制器动作不能为静态方法。除了这些以外,你可以将任何方法作为控制器动作来使用。

3. 理解控制器结果

控制器动作返回一种叫做动作结果(Action Result)的东西。动作结果是控制器动作返回给浏览器请求的东西。

ASP.NET MVC框架支持六种标准类型的动作结果:

  1. ViewResult – 代表HTML及标记。
  2. EmptyResult – 代表无结果。
  3. RedirectResult – 代表重定向到一个新的URL。
  4. RedirectToRouteResult – 代表重定向到一个新的控制器动作。
  5. JsonResult – 代表一个JSON(Javascript Object Notation)结果,它可以用于AJAX应用程序。
  6. ContentResult – 代表着文本结果。

所有这些动作结果都继承自ActionResult基类。

在大多数情况下,控制器动作 ViewResult。例如,代码清单2中的Index()控制器动作返回了一个ViewResult。

代码清单2 – BookController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApp.Controllers
{
     public class BookController : Controller
     {
          public ActionResult Index()
          {
               return View();
          }
     }
}

当一个动作返回一个ViewResult,将会向浏览器返回HTML。代码清单2中的Index()方法向浏览器返回了一个名为Index.aspx的视图。

注意到代码清单2中的Index()动作并没有放回一个ViewResult()。而是调用了Controller基类的View()方法。通常情况下,你并不直接返回一个动作结果。而是调用Controller基类的下列方法之一:

  1. View – 返回一个ViewResult结果。
  2. Redirect – 返回一个RedirectResult 动作结果。
  3. RedirectToAction – 返回一个RedirectToAction动作结果。
  4. RedirectToRoute – 返回一个RedirectToRoute动作结果。
  5. Json – 返回一个JsonResult动作结果。
  6. Content – 返回一个ContentResult动作结果。

因此,如果你想向浏览器返回一个视图,你可以调用View()方法。如果你想要降用户从一个控制器动作重定向到另一个,你可以调用RedirectToAction()方法。举个例子,代码清单3中的Details()动作要么显示一个视图,要么将用户重定向到Index()动作,取决于Id参数是否含有值。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApp.Controllers
{
     public class CustomerController : Controller
     {
          public ActionResult Details(int? Id)
          {
               if (Id == null)
                    return RedirectToAction("Index");
               return View();
          }

public ActionResult Index()
          {
               return View();
          }
     }
}

ContentResult动作结果很特别。你可以使用ContentResult动作结果来将动作结果作为纯文本返回。举个例子,代码清单4中的Index()方法将消息作为了纯文本返回,而不是HTML。

代码清单4 – StatusController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApp.Controllers
{
     public class StatusController : Controller
     {
          public ContentResult Index()
          {
               return Content("Hello World!");
          }
     }
}

当调用StatusController.Index()动作时,并没有返回一个视图。而是向浏览器返回了原始的文本“Hello World!”。

如果一个控制器动作返回了一个结果,而这个结果并非一个动作结果 – 例如,一个日期或者整数 – 那么结果将自动被包装在ContentResult中。举个例子,当调用代码清单5中的WorkController的Index()动作时,日期将自动作为一个ContentResult返回。

代码清单5 – WorkerController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApp.Controllers
{
     public class WorkController : Controller
     {
          public DateTime Index()
          {
               return DateTime.Now;
          }
     }
}

代码清单5中的Index()动作返回了一个DateTime对象。ASP.NET MVC框架自动将DateTime对象转换为一个字符串,并且将DateTime值包装在一个ContentResult中。浏览器将会以纯文本的方式收到日期和时间。

4. 总结

这篇教程的目的是为你介绍ASP.NET MVC中控制器、控制器动作以及控制器动作结果的概念。在第一部分,你学习了如何向ASP.NET MVC项目中添加新的控制器。接下来,你学习了控制器的公共方法是如何作为控制器动作暴露给全世界的。最后,我们讨论了动作结果的各种不同类型,这些动作结果可以从控制器动作中返回。特别地,我们讨论了如何从控制器动作中返回一个ViewResult、RedirectToActionResult和ContentResult。

5. 创建控制器

这篇教程的目的是解释如何来创建新的ASP.NET MVC控制器。你会学习如何通过Visual Studio Add Controller菜单和手工创建类文件,来创建控制器。

5.1 使用Add Controler菜单选项

创建一个新控制的最简单方法是在Visual Studio的解决方案浏览器的Controllers文件夹上点击右键,并且选择Add,Controller菜单项(如图1)。选择这个菜单项打开了Add Controller对话框(如图2)。

图2:添加一个新的控制器

图3:Add Controller对话框

注意到控制器名称的第一部分在Add Controller对话框中高亮显示了。每一个控制器的名称必须以Controller后缀结尾。举个例子,你可以创建一个叫做ProductController的控制器,但是不能创建一个叫做Product的控制器。

NOTE:如果你创建一个控制器,它不含有Controller后缀,那么你将无法调用这个控制器。不要这么做 -- 在犯了这个错误之后,我已经浪费了不计其数的时间。

代码清单1 - Controller/ProductController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MvcApplication1.Controllers
{
    public class ProductController : Controller
    {
        //
        // GET: /Product/

public ActionResult Index()
        {
            return View();
        }

}
}

你应该总是在Controllers文件夹中创建控制器。否则的话,就破坏了ASP.NET MVC的惯例,其他的程序员将会花费更多艰辛的时间来理解你的应用程序。

5.2 创建动作方法

当你创建一个控制器时,你可以选择自动生成Create,Update和Details动作方法(如图3)。如果你选择了这个选项,那么会生成代码2中的控制器类。

图4:自动创建动作方法。

代码清单2 - Controllers\CustomerController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MvcApplication1.Controllers
{
    public class CustomerController : Controller
    {
        //
        // GET: /Customer/

public ActionResult Index()
        {
            return View();
        }

//
        // GET: /Customer/Details/5

public ActionResult Details(int id)
        {
            return View();
        }

//
        // GET: /Customer/Create

public ActionResult Create()
        {
            return View();
        }

//
        // POST: /Customer/Create

[AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(FormCollection collection)
        {
            try
            {
                // TODO: Add insert logic here

return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

//
        // GET: /Customer/Edit/5
 
        public ActionResult Edit(int id)
        {
            return View();
        }

//
        // POST: /Customer/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, FormCollection collection)
        {
            try
            {
                // TODO: Add update logic here
 
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
    }
}

这些生成的方法都只是一些存根方法(stub methods)。你必须自己为客户的创建、更新和显示详情添加实际的逻辑。但是,这些存根方法为你提供了一个漂亮的着手点。

5.3 创建一个控制器类

ASP.NET MVC控制器不过是一个类。如果你喜欢,可以无视Visual Studio便利的控制器创建方式,自己手动来创建一个控制器类。按照这些步骤:

  1. 右键点击Controllers文件夹,并且选择菜单项Add,New Item,然后选择Class模板。
  2. 将新类命名为PersonController.cs,然后点击Add按钮。
  3. 修改产生的类文件,让这个类继承自System.Web.Mvc.Controller基类(见代码清单3)。

图5:创建一个新类

代码清单3 - Controllers\PersonController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication1.Controllers
{
    public class PersonController : System.Web.Mvc.Controller
    {

public string Index()
        {
            return "Hello World!";
        }

}
}

代码清单3中的控制器类公布了一个叫做Index()的动作,它返回字符串“Hello World!”。你可以通过运行应用程序,并且请求像下面这样的URL来调用这个控制器动作:

http://localhost:40071/Person

NOTE:ASP.NET 开发服务器使用一个随机的端口号(例如,40071)。当输入URL来调用控制器时,你需要提供正确的端口号。你可以通过将鼠标悬停在ASP.NET开发服务器的图标上来获得端口号,该图标位于Windows Notification Area(Windows通知区域,屏幕的右下角)。

6. 创建自定义动作

本篇教程的目的是解释如何创建一个新的控制器动作。你会学习到控制器动作的要求。你还会学习如何来阻止将方法公布为控制器动作。

6.1 添加动作到控制器

你可以通过在控制器中添加一个新的方法,将新的动作添加到控制器中。举个例子,代码清单1中的控制器包含了一个叫做Index()和一个叫做SayHello()的动作。这两个方法都公布为了动作。

代码清单1 - Controllers\HomeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index() {
            return View();
        }

public string SayHello() {
            return "Hello!";
        }
   
    }
}

为了将方法作为一个动作公布给全世界,方法必须满足特定的要求:

  • 方法必须是公共的。
  • 方法不能是静态方法。
  • 方法不能使扩展方法。
  • 方法不能是构造函数,访问器,或者设置器。
  • 方法不能拥有开放泛型类型(open generic types)。
  • 方法不能使控制器基类中的方法。
  • 方法不能含有ref或者out参数。

6.2 阻止公共方法被调用

如果你需要在控制器中创建一个公共方法,但是你不想将这个方法发布为控制器动作,那么你可以通过使用[NonAction]特性来阻止该方法被外界调用。举个例子,代码清单2中的控制器含有一个叫做CompanySecrets()的公共方法,它使用[NonAction]特性进行了修饰。

代码清单2 - Controller\WorkController.cs

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class WorkController : Controller
    {
        [NonAction]
        public string CompanySecrets()
        {
            return "This information is secret.";
        }

}
}

如果你试图通过在浏览器地址栏输入/Work/CompanySecrets来调用CompanySecrets()控制器动作,那么你会获得图5所示的错误消息:

图6: 调用一个NonAction方法

Asp.Net MVC 控制器的更多相关文章

  1. ASP.NET MVC 控制器激活(一)

    ASP.NET MVC 控制器激活(一) 前言 在路由的篇章中讲解了路由的作用,讲着讲着就到了控制器部分了,从本篇开始来讲解MVC中的控制器,控制器是怎么来的?MVC框架对它做了什么?以及前面有的篇幅 ...

  2. ASP.NET MVC 控制器激活(二)

    ASP.NET MVC 控制器激活(二) 前言 在之前的篇幅中,用文字和图像来表示了控制器的激活过程,描述的角度都是从框架默认实现的角度去进行描述的,这样也使得大家都可以清楚的知道激活的过程以及其中涉 ...

  3. ASP.NET MVC 控制器激活(三)

    ASP.NET MVC 控制器激活(三) 前言 在上个篇幅中说到从控制器工厂的GetControllerInstance()方法来执行控制器的注入,本篇要讲是在GetControllerInstanc ...

  4. 学习ASP.NET MVC(二)——我的第一个ASP.NET MVC 控制器

    MVC全称是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范,用一种业务逻辑和数据显示分离的方法组织代码,将 ...

  5. 详解ASP.NET MVC 控制器

    1   概述 在阅读本篇博文时,建议结合上篇博文:详解ASP.NET MVC 路由  一起阅读,效果可能会更好些. Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务端的 ...

  6. 【ASP.NET MVC系列】浅谈ASP.NET MVC 控制器

    ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...

  7. 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射

    使用Code First建模自引用关系笔记   原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...

  8. ASP.NET MVC控制器Controller中参数

    前述文章参见:ASP.NET MVC控制器Controller 绪论 之前的控制器返回的均为常量字符串,接下来展示如何获取请求传来的参数,而返回"动态"的字符串. 可以在操作方法B ...

  9. asp.net MVC控制器中返回JSON格式的数据时提示下载

    Asp.net mvc在接收的是JSON格式的数据,但是奇怪的是在IE中提示下载文件,其他浏览器中一切正常,下载后,里面的内容就是在控制器中返回的数据.代码如下: 视图中js代码: $("# ...

随机推荐

  1. C# 如何利用反射来加载程序集,并调用程序集中有关类的方法【转】

    假设在C盘根目录下有个Dog的Dll程序集文件,该程序集文件中包含类Dog 该类中有个狗叫几声的方法,如何通过反射来加载这个C:\Dog.dll,并且调用Dog类里面的Sound方法呢: public ...

  2. [置顶] java web 动态服务器

    写了一个java web 动态服务器,主要通过内部类来实现,动态类使用了外部类,采用了 classforname 实例化,动态类的构造方法不能带参数, 效果都出来了,分享给有需要的 朋友.判断做的不够 ...

  3. Cannot access empty property

    致命错误:不能够进入此空值,位于E:\sunlion\web\down\class\db_sql.php 代码 <?php Class TestClass1{ var $class2; publ ...

  4. i = i++ 在java字节码层面的分析

    有这么一段代码: package zl.test; public class PcodeTest { /** * @param args */ public static void main(Stri ...

  5. JSEL 表达式

    JSTL标签库的使用是为类弥补html表的不足,规范自定义标签的使用而诞生的.在告别modle1模式开发应用程序后,人们开始注重软件的分层设计,不希望在jsp页面中出现java逻辑代码,同时也由于自定 ...

  6. Programming C#.Classes and Objects.传递参数

    ref 关键字通过引用(而非值)传递参数. 通过引用传递的效果是,对所调用方法中的参数进行的任何更改都反映在调用方法中. 说明: 不要混淆通过引用传递的概念与引用类型的概念. 这两种概念是不同的. 无 ...

  7. C语言版推箱子

    推箱子源代码初步: #include<stdio.h> #include<conio.h> #include<stdlib.h> #define boolean i ...

  8. Java学习之Java中常用对象

    java的几种对象(PO,VO,DAO,BO,POJO)解释     一.PO:persistant object 持久对象,可以看成是与数据库中的表相映射的java对象.最简单的PO就是对应数据库中 ...

  9. 事件绑定之.bind()

    .bind(eventType[,eventData],handler(eventObject)) 描述:为一个元素绑定一个事件处理程序,bind()绑定方法的时候元素必须已经存在. -eventTy ...

  10. C语言学习 —— 字符串的学习(一)

    这是本人在学习 C语言有关 字符串内容 时的相关笔记 由于本人技术有限,如有错误,还望指正 C语言中数据类型中只有 字符型(char),而 char型 变量一次只能存储一个字符,在日常工作中经常需要定 ...