一、控制器
- 控制器角色
- 中转作用
- 承上启下,根据用户输入,执行响应行为(动作方法)
- 在行为中调用模型的业务逻辑,返回给用户结果(视图)
- 中介角色
- 分离视图和模型,让视图和模型各司其职,控制器负责二者交互
- 只负责数据传送,不负责处理
- 中转作用
- 控制器类
- 所有控制器的基类都是Controller
- Controller类位于System.Web.Mvc命名空间,继承自ControllerBase类
- ControllerBase类实现了Icontroller接口中的Execute方法,在路由器搜索到相应的控制器后,就会调用Execute方法进入控制器的处理
- ControllerBase类
- 属性
- ControllerContext:获取或者设置控制器上下文
- ValidateRequest:获取或设置一个值,该值指示是否为此请求启用请求验证
- ValueProvider:获取或设置控制器的值
- ViewData:获取或设置数据的字典
- ViewBag:获取动态视图数据字典
- TempData:获取或设置可以在不同控制器之间传递数据的字典
- 任务
- 定位:找到对应的动作方法
- 获取参数:获取动作方法的参数
- 处理错误:在执行动作方法中可能出现的错误
- 渲染视图:提供默认的WebFormViewFactory类来渲染ASP.NET视图
- 属性
二、动作方法的参数与模型映射
- 获取URL和表单数据
//在动作方法中获取URL和表单数据并处理 public ActionResult GetList() { //获取提交的数据 string className = Request.Params["className"]; //获取数据 string stuId = Request.QueryString["stuId"]; //数据处理....... List<Student> stuList = new StudentManage().GetStudentsByClass(className); } | | ↓ //在动作方法中使用"参数映射" public ActionResult GetList(string className) { List<Student> stuList = new StudentManage().GetStudentsByClass(className); //参数进行了自动映射,参数名称与视图中的参数名称必须一致,不区分大小写,参数类型也要相同 }
参数映射的好处:不需要手工获取参数并作类型转换,在多个参数是非常明显
-
参数映射的优先级
- 表单数据 > 路由数据 > URL数据
- 参数名要和目标数据参数名一致(不区分大小写)
- 参数数据类型要和来源数据类型一致
- 参数映射失败解决方法:将值类型定义为可为空类型,可选参数,如 int?等等
- 映射模型
- 基本步骤:
- 获取表单数据
- 构造实体模型
- 调用业务逻辑方法并传递模型
public ActionResult Edit() { Student object = new Student() { StudentId = Convert.ToInt32(Request.Params["stuId"]), StudentName = Request.Params["stuName"], Birthday = Convert.ToDateTime(Request.Params["birthday"]), .... ... }; int result = new StudentManage().ModifyStudent(object); return View(); } | | ↓ //映射实体 public ActionResult Edit(Student object) { //需要在视图中将视图中name属性名设置的和实体属性名称相同, //且视图要为强类型视图,则可以直接映射实体对象 int result = new StudentManage().ModifyStudent(object); return View(); }
- 基本步骤:
三、动作方法特性与ActionResult
- 动作方法的同名问题
- 重载一个控制器动作方法
public ActionResult GetList(string className) { List<Student> stuList = new StudentManage().GetStudentsByClass(className); return View(); } public ActionResult GetList() { //获取提交的数据 string className = Request.Params["className"]; //获取数据 string stuId = Request.QueryString["stuId"]; //数据处理....... List<Student> stuList = new StudentManage().GetStudentsByClass(className); } //路由系统不能根据方法参数取定位动作方法
- 解决方法
- HTTP请求谓词方法:针对请求类型定位方法,解决同名冲突问题
- 关于Http谓词
- 特点:经常使用,如果不加上该特性,默认动作方法接收所有谓词请求
- 一般开发中都会加上谓词,限定请求谓词类型
特性名 说明 HttpGet 针对Get请求 HttpPost 针对Post请求 HttpDelete 针对Delete请求 HttpPut 针对Put请求 [HttpPost]//请求谓词 public ActionResult GetList(string className) { List<Student> stuList = new StudentManage().GetStudentsByClass(className); return View(); } [HttpGet]//请求谓词 public ActionResult GetList() { //获取提交的数据 string className = Request.Params["className"]; //获取数据 string stuId = Request.QueryString["stuId"]; //数据处理....... List<Student> stuList = new StudentManage().GetStudentsByClass(className); }
- 关于Http谓词
- NonAction特性
- 可以将控制器中的方法声明为"非动作方法"
- 对于控制器内部使用的方法非常有用,加上该特性后,外部不能访问,即可解决同名冲突问题
[NonAction] public ActionResult GetList() { //获取提交的数据 string className = Request.Params["className"]; //获取数据 string stuId = Request.QueryString["stuId"]; //数据处理....... List<Student> stuList = new StudentManage().GetStudentsByClass(className); }
- ActionName特性
- 为动作方法"重新命名",解决同名冲突问题
- 视同中使用时,需要修改成"重新命名"后的方法
- 特别注意:当动作方法应用了ActionName特性后,如果动作方法内部使用View()方法调用视图(也就是不指定视图名称),则调用的是和ActionName设置值同名的视图
[ActionName("GetAllList")] public ActionResult GetList() { //获取提交的数据 string className = Request.Params["className"]; //获取数据 string stuId = Request.QueryString["stuId"]; //数据处理....... List<Student> stuList = new StudentManage().GetStudentsByClass(className); return View();//如果使用ActionName,返回View()不写参数时候,默认返回ActionName的视图 } //视图中调用路径 <form method="post" action="/Student/GetAllList"> ..... .... ... </form>
- HTTP请求谓词方法:针对请求类型定位方法,解决同名冲突问题
- 重载一个控制器动作方法
- ActionResult详解
- 隐式动作类型
- 动作方法返回类型可以是ActionResult以外的类型
public int Sum(int num1,int num2) { int sum = num1 + num2; return sum; } public void WriteLog() { System.IO.File.WriteAllText(@"D:\Syslog.txt","保存文件"); }
- 类型说明
- int类型 ->ContentResult类型
- void -> EmptyResult类型
- 动作方法返回类型可以是ActionResult以外的类型