一、理解控制器
1.1、什么是控制器
控制器是包含必要的处理请求的.NET类,控制器的角色封装了应用程序逻辑,控制器主要是负责处理请求,实行对模型的操作,选择视图呈现给用户。
简单理解:实现了IController接口,修饰符必须是public,不能是抽象的,不能是泛型的,类名必须以Controller结尾。
在MVC框架中,控制器类必须实现System.Web.Mvc命名空间下的IController接口,如上图所示,这是一个非常简单的接口,该接口仅有一个Execute方法,当请求该控制器时Execute方法被调用。通过实现IController接口,你可以创建控制器类。
1.2、控制器的作用
a、每一个针对应用程序的请求,都是通过控制器自由地选择合适的方式来处理的,只要它不偏离到视图(View)和模型(Model)所负责的区域。
b、不要把业务或数据存储的逻辑放到控制器里面,也不要创建用户接口。
1.3、创建实现IController接口的控制器
示例: 创建一个实现Icontroller接口的类,读取路由数据,并生成数据写入响应。
在Controllers文件夹下创建一个名为MyFirstController的类,实现IController接口并添加如下代码
运行该应用程序并在地址栏导航到/MyFirst,便可以看到此控制器产生的输出。
创建一个类通过实现IController接口,MVC框架会将其视为一个控制器,并将请求发送给它,而且在如何处理和响应请求上没有任何限制,这是一个很好的示例,因为它向你展示了MVC框架的可扩展性,但用这种方式编写一个复杂的应用程序是非常困难的。
1.4、创建继承于Controller类的控制器
通过System.Web.Mvc.Controller类你可以派生你的控制器,System.Web.Mvc.Controller类是大多数Web开发人员需要熟悉的,用来对请求处理提供支持的一个类,Controller提供了以下三个关键特性。
(1)、动作方法(Action Method):一个控制器的行为被分解成多个方法(而并非只有唯一的Execute()方法)。每个动作方法被暴露给不同的URL,并通过从输入请求提取的参数进行调用。
(2)、动作结果(Action Result):你可以返回一个描述动作结果的对象(例如:渲染一个视图,或重定向到一个不同的URL或动作方法),然后通过该对象实现你的目的。这种指定结果和执行之间的分离简化了单元测试。
(3)、过滤器(Filter):你可以把可重用的行为封装成过滤器,然后通过在代码中添加特性的的方式,把这种行为标注到一个过多个控制器或动作方法上。
除非在头脑中有一个非常明确的需求,否则创建控制器最好的办法就是通过Controller类进行派生,这也正是你在Visual Studio中添加一个控制器,Visual Studio为你所做的事情。
在Controllers文件夹下创建一个名为MySecondController的类,继承与Controller类,然后添加一个动作方法TestAction并编写如下代码返回一个动作结果,最后再该动作方法内右键添加对应的视图。
运行应用程序并导航到/MySecond/TestAction浏览结果如下:
作为Controller类的一个派生类,所要做的工作是实现动作方法、获取所需要的各种输入,以对请求进行处理,并生成一个适当的响应。后面的内容将介绍数据的接收与响应。
二、控制器对数据的接收
2.1、数据来源
a、查询字符串值 b、表单数据 c、路由数据
控制器需要经常访问来自输入请求的数据,如查询字符串、表单数据、以及由路由系统根据输入的URL解析得到的参数的值。访问这些数据有三种主要方式。
(1)、从上下文对象提取。
(2)、作为参数被传递给动作方法(Action Method)而形成的数据。
(3)、明确调用框架的模型绑定(Model Binding)功能。
注意:参数名称是忽略大小写的,如Request["Test"]与Request["test"]结果是一样的。如下图:
View部分
Controller部分
2.2、通过上下文对象获取数据
当创建一个从Controller基类派生的控制器时,就能够访问一组非常便利的属性,这些属性包括:Request、Response、RouteData、HttpContext、Server等,每一个属性都包含了请求不同方面的的信息。在Action方法里是可以使用任何Context对象来访问这些属性。例如:
public ActionResult Index() { string userName = User.Identity.Name; string serverName = Server.MachineName; string clientIP = Request.UserHostAddress; DateTime dateStamp = HttpContext.Timestamp; string oldProductName = Request.Form["OldName"]; string newProductName = Request.Form["NewName"]; ViewBag.Message = "本机的IP是:" + clientIP; return View(); }</div>
可以利用VS智能感知,在动作方法中输入this.找到这些可用的上下文信息。
2.3、使用动作(Action)方法参数
2.3.1、使用Action方法参数
下面的方式是不是比上面的方法更优雅易读呢?不过需要注意的是:Action方法里面是不允许有ref或out参数的,虽然编译不会报错但运行时会抛出一个异常。如下所示。
MySecond控制器代码如下:
Index视图代码如下:
运行结果如下:
2.3.2、理解参数对象实例化
Controller基类使用叫做“值提供器(Value Provider)”和“模型绑定器(Model Binder)”的MVC框架组件来获取动作方法的参数值。值提供器将可用的数据项集合呈现给控制器。有一组内建的值提供器从Request.For
m、Request.QueryString、Request.Files、RouteData.Values获取数据项,然后这些值会被传递给模型绑定器,模型绑定器会尝试将这些数据映射成动作方法参数的数据类型。默认的模型绑定能够创建和填充任何.NET类型的对象,包括自定义的类型和集合。
2.3.3、理解可选参数与必须的参数
如果MVC框架找不到引用类型参数(如:string或object)的值,动作方法仍然会被调用,但对该参数会使用一个null值,若找不到值类型参数(如:int或double)的值则会抛出一个异常,并且不会调用动作方法。
a、值类型参数是必须被赋值的。如果想让此参数和引用类型参数一样,可以定义成int?如:public ActionResult Index(int? num),当依然没有值时,不会发生异常,而是会传递null值。
b、引用类型的参数是可选的。为了使它成为必须的(保证一个非空的值被传递),在动作(Action)方法上添加一些代码拒绝null。例如,在该值等于null时,抛出一个ArgumentNullException异常。
2.3.4、指定默认参数值
如果希望处理不含动作方法参数的请求,但又不想在代码中检查null值或抛出异常,可以使用C#的可选参数特性来代替。如下所示:
public ActionResult List(string query = "all", int page = 1) { //此处省略代码N行... return View(); }</div>
在定义参数时,通过对参数赋值的办法,可以将参数标记为可选的,如上诉代码中,给query和page参数提供了默认值。MVC框架会试图通过请求为这些参数获取值,但如果没有值可用,那么将用所指定的默认值代替。
对于string类型参数query,注意string类型是引用类型,这意味着不需要检查null值。如果请求为指定查询字符串,那么该动作(Action)方法将以字符串“all”进行调用。对于int类型参数,注意int类型是值类型,在没有page值时,请求不会导致错误,该方法将以默认值“1”进行调用。
三、控制器对数据的响应
3.1、理解动作结果(Action Result)
原理:
a、MVC框架接收从Action方法返回的ActionResult对象,并调用定义在Ac
您可能想查找下面的文章:
- 详解ASP.NET MVC 常用扩展点:过滤器、模型绑定
- ASP.NET MVC从视图传参到控制器的几种形式
- ASP.NET MVC 4 中的JSON数据交互的方法
- ASP.NET MVC制作404跳转实例(非302和200)
- 详解ASP.NET MVC 利用Razor引擎生成静态页
- 详解ASP.NET MVC 解析模板生成静态页(RazorEngine)
- ASP.NET MVC4 利用uploadify.js多文件上传
- ASP.NET mvc4中的过滤器的使用
- Asp.net MVC下使用Bundle合并、压缩js与css文件详解
- 详解Asp.Net MVC——控制器与动作(Controller And Action)