APS.NET MVC + EF (05)---控制器

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>&#160;&#160;&#160;&#160;</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 案例:用户注册(或信息添加)

   

   

   

   

猜你喜欢

转载自www.cnblogs.com/mrfang/p/10776034.html
今日推荐