Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务端的交互,并且负责协调Model与View之间数据传递,是ASP.NET MVC框架核心。Controller为ASP.NET MVC框架的核心组成部分,其主要负责处理浏览器请求,并决定响应什么内容给浏览器,但并不负责决定内容应如何显示(View的职责)。

5.1 动作方法

Controller本身就是一个类(Class),该类别有许多方法(Method),这些方法中只要是公开方法(public method)就会被视为是一个动作(Action)或动作方法(Action Method),并可以通过该动作方法接收客户端传来的请求和决定响应的视图(View)。

Controller应具备如下几个基本条件。

(1)Controller必须为公开类别;

(2)Controller名称必须以Controller结尾;

(3)必须继承自ASP.NET MVC内建的Controller类别,或实现IController自定义类别;

(4)动作方法必须为公开方法,任何非公开的方法如声明为private或protected的方法都不会被视为一个动作方法;

5.1.1 同名方法问题

在一般的类中,方法是可以重载的,但是动作方法是不可以重载的。如示例1中代码在编译的时候不会有任何问题,但在运行时就会出现如图5-1所示的错误。

示例1

public class AccountController : Controller

{

public ActionResult Register()

{

//省略代码

}

public ActionResult Register(User user)

{

//省略代码

}

}

图5-1 动作方法不明确

上面的错误说明ASP.NET MVC 路由系统不能凭借方法参数去定位动作方法。

5.1.2 动作方法上的特性

解决同名方法的问题一般有3种方法,3种方法都是要在动作方法上应用特性。

  1. 谓词筛选特性

    在ASP.NET MVC中,提供了区分不同请求的请求谓词筛选特性,如HttpGet、

    HttpPost、HttpDelete和HttpPut,分别对应Get、Post、Delete和Put几种请求。对于示例1的代码,可以按照示例2的方式应用特性。

    示例2

public class AccountController : Controller

{

[HttpGet]

public ActionResult Register()

{

//省略代码

}

[HttpPost]

public ActionResult Register(User user)

{

//省略代码

}

}

示例2的代码表示,Register( ) 方法只能对应到Get方式的请求,Register(User user)方法只能对应到Post方式请求。

  1. NonAction特性

    若控制器某个方法特性为NonAction,即使该Action方法是"公开方法",也不会被被看作Action来运行。

    主要用途:

  • 保护Controller中的特定公开方法不要发布到Web上;
  • 功能尚未开发完成就要进行部署,暂时不想将此方法删除。

示例3

public class HomeController : Controller

{

public ActionResult Index()

{

return View();

}

[NonAction]

public ActionResult Index(int id)

{

return View();

}

}

  1. ActionName特性

    在ASP.NET MVC中,路由中定义的Action的名称和控制器中定义的动作方法的名称命名通常是一致的,但这只是一般的方法,也可以让Action和动作方法的名称不一致,用法如示例4所示。

    示例4

public class HomeController : Controller

{

public ActionResult Register()

{

//省略代码

}

[ActionName("RegisterUser")]

public ActionResult Register(User user)

{

//省略代码

}

}

示例5中,将Register(User user)方法的Action名声明为RegisterUser,解决了同名冲突问题。使用这种方法,需要注意在视图中提交表单的Action属性也要做相应的修改,如下面的代码。

<form action="/Account/RegisterUser" method="post">

</form>

5.1.3 动作方法的结果类型

在前面的内容中,我们习惯使用ActionResult作为动作方法的返回类型,通过View()方法返回对象。其实View()方法的返回类型是ViewResult,ViewResult和ActionResult的关系图5-2所示。

图5-2 ActionResult类关系图

在动作方法定义中,很显然使用了多态,ActionResult是一个抽象类,返回的对象为子类类型。在实际的开发中,有时候不需要 向客户端输出HTML,而是文件、文本等其它一些输出,这时候子类就派上用场了,常用的输出类型如表5-1所示。

表5-1 常用输出类型

输出类型

说 明

EmptyResult

输出空内容

ContentResult

将指定内容作为文本输出

JsonResult

输出JSON字符串

JavaScriptResult

输出JavaScript文件

RedirectResult

指定的 URI 来执行重定向

RedirectToRouteResult

指定路由值来执行重定向

FilePathResult

指定文件路径来输出文件

FileContentResult

指定字节数组来输出文件

FileStreamResult

指定流来输出文件

ViewResult

调用视图文件输出视图

在实际使用这些类型时,不需要在动作方法中实例化这些类的实例再返回,再Controller类中,已经定义了返回这些类型实例的方法,直接调用即可。如View()方法。常用的方法如表5-2所示。

表5-2 常用控制器输出方法

类型

方 法

EmptyResult

ContentResult

Content(string content)

JsonResult

Json(object data)

JavaScriptResult

JavaScript(string script)

RedirectResult

Redirect(string url)

RedirectToRouteResult

RedirectToAction(string actionName)

FilePathResult

File(string fileName, string contentType)

FileContentResult

File(byte[] fileContents, string contentType)

FileStreamResult

File(Stream fileStream, string contentType)

ViewResult

View(string viewName)

各种方法的用法如示例5所示。

示例5

public class HomeController : Controller

{

public ActionResult Index()

{

return View();

}

//页面跳转

public ActionResult RedirectTest()

{

return Redirect("/Home/Detail");

}

//页面跳转

public ActionResult RedirectToRouteTest()

{

return RedirectToRoute(new { controller = "Home",

action = "Detail", id = 1, cate = "test" });

}

//页面跳转

public ActionResult RedirectToActionTest()

{

return RedirectToAction("Detail", new { id = 1,

cate = "test" });

}

//输出JSON文件

public ActionResult JsonTest()

{

var book = new

{

bookid = 1,

bookName = "精通ASP.NET MVC",

author = "Fangyc",

publishData = DateTime.Now

};

return Json(book, JsonRequestBehavior.AllowGet);

}

//输出JavaScript文件

public ActionResult JavaScriptTest()

{

string js = "alert('Welecome to ASP.NET MVC!')";

return JavaScript(js);

}

//按文件路径输出文件

public ActionResult FilePathTest()

{

return File("~/Content/rain.mp3", "audio/mp3");

}

//对字符串编码并输出文件

public ActionResult FileContentTest()

{

string content = "Welcome to ASP.NET MVC!";

byte[] contents = System.Text.Encoding.UTF8.GetBytes(content);

return File(contents, "text/plain");

}

//用文件流输出文件

public ActionResult FileStreamTest()

{

string content = "Welcome to ASP.NET MVC!";

byte[] contents = System.Text.Encoding.UTF8.GetBytes(content);

FileStream fs = new FileStream(

Server.MapPath("~/Content/ASP.NET MVC.pdf"),

FileMode.Open);

return File(fs, "application/pdf");

}

//输出简单文本

public ActionResult ContentTest()

{

string content = "<h1>Welcome to ASP.NET MVC!</h1>";

return Content(content);

}

}

在ASP.NET MVC中,动作方法的返回类型并不一定是ActionResult类型,也可以是其它任何类型,甚至是void类型,如下面的代码。

public int Sum(int num1,int num2)

{

int sum=num1+num2;

return sum;

}

public void log()

{

File.WriteAllText(@"D:\log.test", "保存文件");

}

上述这种返回类型的动作方法称为隐式动作方法,ASP.NET MVC 自动做了一些处理,将void类型对应到EmptyResult类型,将其它非ActionResult类型对应到ContentResult类型。

5.2 动作方法参数

我们以前在动作方法中获取 URL 和表单数据的方法,可能会采用如下方式:

string name=Request.Forms["name"];

string id=RouteData.Values["id"];

除了上面的方法外,ASP.NET MVC 还提供了更加便利的方法。

5.2.1 简单类型映射

在ASP.NET MVC中,可以把路由数据、URL数据、表单数据自动映射到动作方法参数中,这些参数可以直接定义为基本数据类型或string类型。

示例6

public ActionResult Detail()

{

int id = Request.QueryString["id"] != null?

Convert.ToInt32(RouteData.Values["id"]):0;

// 省略代码

return View();

}

public ActionResult Detail(int id=0)

{

// 省略代码

}

示例6中,第二个方法参数使用了数据映射的功能,RouteData.Values["id"]的值可以自动映射到参数id中。

示例7

public ActionResult List()

{

int pageCount = 0;//总页数

int categoryId = Request.QueryString["categoryId"] != null

? Convert.ToInt32(Request.QueryString["categoryId"]) : 1;

//页序号

int pageIndex = Request.QueryString["pageIndex"] != null

? Convert.ToInt32(Request.QueryString["pageIndex"]) : 1;

//排序字段

string order = Request.QueryString["order"] != null

? Convert.ToString(Request.QueryString["order"]) : "PublishDate";

BookManager manager = new BookManager();

List<Book> list = manager.GetBooks(

categoryId, this.PageSize, pageIndex, ref pageCount, order);

}

public ActionResult List(int categoryId = 1, int pageIndex = 1,

string order = "PublishDate")

{

int pageCount = 0;//总页数

BookManager manager = new BookManager();

List<Book> list = manager.GetBooks(categoryId, this.PageSize, pageIndex, ref pageCount, order);

}

示例7中,第二个方法参数使用了数据映射的功能,该方法定义了多个参数,各个参数的值都由Request.QueryString映射而来。

示例8

public ActionResult LogIn()

{

string userName=Request.Form["userName"];

string password=Request.Form["password"];

string returnUrl=Request.Form["returnUrl"];

// 省略代码

}

public ActionResult LogIn(string userName, string password, string returnUrl)

{

// 省略代码

}

从上述三个示例可以看出,使用动作方法参数自动映射,简化了大量代码。

获取数据的优先级依次是表单数据--->路由数据--->URL数据。在定义动作方法参数时,需要保证以下两点。

  • 参数名要和目标数据参数名一致(不区分大小写)。
  • 参数数据类型要和来源数据的目标数据类型一致。

对于值类型参数的数据,如果从来源数据获取不到相应的值,就会出现参数映射的运行时错误,一般把这种参数直接声明为可空类型或可选参数。

5.2.2 映射模型

动作方法参数的映射不仅仅是简单类型,还可以是复杂类型。如示例 8所示。

示例8

<form action="/Account/RegisterUser1" class="member_form" id="Form1"

method="post">

<p>

<label><span>*</span>用户名</label>

<input class="opt_input" name="LoginId" type="text"/>

5-12个字符或数字组成,可用中文名

</p>

<p>

<label><span>*</span>真实姓名</label>

<input class="opt_input" name="Name" type="text"/>

</p>

<p>

<label><span>*</span>密    码</label>

<input class="opt_input" name="LoginPwd" type="password"/>

</p>

<p>

<label><span>*</span>确认密码</label>

<input class="opt_input" name="PasswordConfirm" type="password" />

</p>

<p>

<label><span>*</span>电子邮件</label>

<input class="opt_input" name="Mail" type="text" />

</p>

<!-- 省略其它代码 -->

</form>

// 控制器代码

public ActionResult RegisterUser(User user)

{

UserManager manager = new UserManager();

if (!manager.Register(user))

{

//省略代码

}

return View("Register", user);

}

示例8的方法中,并没有创建User对象,也没有给其属性赋值。其实这些工作是ASP.NET MVC通过分析User对象的属性和表单中元素按名称进行匹配并进行赋值。通过这种方式,自动完成对象创建和初始化赋值工作。这也被称为ASP.NET MVC的模型自动绑定功能。

5.3 案例:用户注册(或信息添加)

APS.NET MVC + EF (05)---控制器的更多相关文章

  1. APS.NET MVC + EF (06)---模型

    在实际开发中,模型往往被划分为视图模型和业务模型两部分,视图模型靠近视图,业务模型靠近业务,但是在具体编码上,它们之间并不是隔离的. 6.1 视图模型和业务模型 模型大多数时候都是用来传递数据的.然而 ...

  2. APS.NET MVC + EF (11)---过滤器

    过滤器本质就是对动作方法的执行过程进行干预,这种干预可以影响动作方法执行的各个过程.ASP.NET MVC 提供了4种类型的接口,并在接口中定义了各种成员,代表代码执行的各个阶段,这些接口和成员如表1 ...

  3. APS.NET MVC + EF (08)---数据注解和验证

    对于Web开发人员来说,用户输入验证一直是一个挑战.不仅在客户端浏览器中需要执行验证逻辑,在服务器端也需要执行.如果觉得验证是令人望而生畏的繁杂琐事,ASP.NET MVC框架提供了数据注解的方式帮助 ...

  4. APS.NET MVC + EF (07)---表单和HTML辅助方法

    在ASP.NET MVC中,可以借助HtmlHelper 对象来输出页面内容,提高开发效率.下面,我们将介绍一些常用的辅助方法. 7.1 HTML辅助方法 BeginForm 该辅助方法主要用来产生& ...

  5. APS.NET MVC + EF (04)---路由和数据传递

    4.1 视图引擎 ASP.NET MVC 提供两种视图引擎:ASPX(C#)和Razor(CSHTML),推荐使用Razor. 4.1.1 Razor的语法 在Razor视图中,所有的服务器端代码都是 ...

  6. APS.NET MVC + EF (03)---初始MVC

    3.1 MVC简介 MVC(Model-View-Controller,模型—视图—控制器模式)用于表示一种软件架构模式.它把软件系统分为三个基本部分:模型(Model),视图(View)和控制器(C ...

  7. APS.NET MVC + EF (14)---项目框架搭建

    一:框架搭建     1:先创建Model. 2:创建数据访问接口层.IUserInfoDal 在该接口中定义了常见的方法CURD以及分页方法. public interface IUserInfoD ...

  8. APS.NET MVC + EF (10)---使用AJAX

    在Web系统中,Ajax技术已经成为提高用户体验的必备技术.开发Ajax程序,涉及两方面的内容:一是客户端技术,二是服务器端技术. (1)客户端技术 核心工作是通过JavaScript向服务器发送数据 ...

  9. APS.NET MVC + EF (02)---深入理解ADO.NET Entity Framework

    2.7 深入理解Entity Framework 性能问题几乎是一切ORM框架的通病,对于EF来说,引起性能低的原因主要在以下几个方面. 复杂的对象管理机制为了在.NET中更好地管理模型对象,EF提供 ...

随机推荐

  1. c语言基础之getopt()

    getopt() #include <unistd.h> int getopt(int argc, char * const argv[], const char *optstring); ...

  2. React源码 ReactDOM.render

    在 react 当中,主要创建更新的有三种方式 1.ReactDOM.render || hydrate  这两个api都是要把这个应用第一次渲染到我们页面上面,展现出来整个应用的样子的过程,这就是初 ...

  3. 11-赵志勇机器学习-DBSCAN聚类

    (草稿) 两点关系的三种定义: 1. 直接密度可达:A在B的邻域内: 2. 密度可达:AB之间存在,直接密度可达的点串: 3. 密度连接:AB之间存在点k,使得Ak和Bk都密度可达: 过程: 1. 对 ...

  4. volatile 关键字 和 i++ 原子性

    package com.mozq.multithread; /** * 深入理解Java虚拟机 volatile 关键字 和 i++ 原子性. */ public class VolatileTest ...

  5. Layui 新标签打开

    原文:https://blog.csdn.net/sr_www/article/details/81394365 layuiAdmin 后台管理模板 iframe版 在新标签中打开网页 / 在ifra ...

  6. webpack 配置多入口文件,输出多出口文件

    const path = require('path') module.exports = { // 入口文件的配置项 entry: { // 入口文件 entry: './src/entry.js' ...

  7. windows 安装 numpy scipy matplotlib scikit-learn

    直接使用  pip install 包名  的方法安装不成功 下载第三方安装包 下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy  根据系统 ...

  8. concurrent (一)concurrent

    参考文档: 跳跃表原理分析:https://blog.csdn.net/a1259109679/article/details/46442895 一.阻塞队列 ArrayBlockingQueue : ...

  9. Tomcat对取消post长度限制

    1.Tomcat 默认的post参数的最大大小为2M, 当超过时将会出错,可以配置maxPostSize参数来改变大小. 从 apache-tomcat-7.0.63 开始,参数 maxPostSiz ...

  10. 【视频开发】【计算机视觉】相机标定(Camera calibration)原理、步骤

    相机标定(Camera calibration)原理.步骤 author@jason_ql(lql0716)  http://blog.csdn.net/lql0716 在图像测量过程以及机器视觉应用 ...