ASP.NET MVC系列:Controller/Action
1. Controller
Controller是ASP.NET MVC的核心,负责处理浏览器请求,并作出响应。Cotroller本身是一个类(Class),该类有多个方法(Method)。在这些方法中,只要是公开方法,该方法将被视为一个动作(Action);只要有动作存在,就可以通过该动作方法接收网页请求并决定应响应的视图。
1.1 Controller的基本要求:
◊ Controller必须是公共(Public)类;
◊ Controller的名称必须以“Controller”结尾;
◊ 必须继承ASP.NET MVC的Controller类,或继承实现IController接口的自定义类,或自身实现IController接口;
◊ 所有方法必须为Public方法。该方法可以没有参数,也可以有多个参数。
2. Action名称选择器
当通过ActionInvoker选取Controller中的公共方法时,默认会用Reflection方式取得Controller中具有相同名称的方法。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { /// <summary> /// http://localhost/Home/Index /// </summary> public ActionResult Index() { return View(); } } }
可以通过在Action上使用ActionName属性(Attribute)来指定Action,这就是动作名称选择器(Action Name Selector)。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { /// <summary> /// http://localhost/Home/Default /// </summary> [ActionName("Default")] public ActionResult Index() { return View(); } } }
3. 动作方法选择器
在通过ActionInvoker选取Controller中的公共方法是,ASP.NET MVC还提供了一个特性,动作方法选择器(Action Method Selector),以帮助ActionInvoker选择适当的Action。
3.1 NonAction属性
若将NonAction属性应用在Controller中的Action方法上,即使该Action方法是公共方法,也会告知ActionInvoker不要选取这个Action来执行。这个属性主要用来保护Controller中的特定公共方法不会发布到Web上。或是当功能尚未开发完成就要进行部署时,若暂时不想将此方法删除,也可以使用这个属性。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { [NonAction] public ActionResult Index() { return View(); } } }
将Action方法的“public”改成“private”,也可以达到同样的目的。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { private ActionResult Index() { return View(); } } }
3.2 HttpGet属性、HttpPost属性、HttpDelete属性和HttpInput属性
HttpGet、HttpPost、HttpDelete、HttpInput属性是动作方法选取器的一部分,这些属性常用在需要接收窗口数据的时候。如:创建两个同名的Action,一个应用[HttpGet]属性来显示窗口HTML,另一个应用[HttpPost]属性来接收窗口发送的值。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Libing.Portal.Web.Models; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } [HttpGet] public ActionResult Create() { return View(); } public ActionResult Create(Product product) { //UpdateModel(product); return RedirectToAction("Index"); } } }
4. ActionResult类
ActionResult类是Action执行的结果,但ActionResult中并不包含执行结果,而是包含执行响应时所需要的信息。当Action返回ActionResult类之后,会由ASP.NET MVC执行。
ASP.NET MVC定义的ActionResult如下表所示:
类 | Controller辅助方法 | 用途 |
---|---|---|
ContentResult | Content | 返回一段用户自定义的文字内容 |
EmptyResult | 不返回任何数据,即不响应任何数据 | |
JsonResult | Json | 将数据序列转化成JSON格式返回 |
RedirectResult | Redirect | 重定向到指定的URL |
RedirectToRouteResult | RedirectToAction、RedirectToRoute | 重定向到Action或Route |
ViewResult | View | 使用IViewInstance接口和IViewEngine接口,实际输出的数据是IViewEngine接口和View |
PartialViewResult | PartialView | 与ViewResult类相似,返回的是“部分显示” |
FileResult | File | 以二进制串流的方式返回一个文件数据 |
JavaScriptResult | JavaScript | 返回JavaScript指令码 |
以上的动作结果都继承自ActionResult基类。
4.1 ViewResult
ViewResult类是在ASP.NET MVC中最常用的ActionResult类,用于返回一个标准的视图。通过Controller辅助方法,可以定义输出的View名称。
4.1.1 返回默认的页面
返回的默认页面与Action的名称相同
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } } }
public ViewResult Index() { return View(); }
4.1.2 指定页面名称的响应
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public ActionResult Index() { return View("Default"); } } }
4.1.3 指定的页面不存在
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public ActionResult Index() { return View("NotExists"); } } }
当在Views目录下找不到页面时,出现下面的提示信息。
4.2 PartialViewResult
PartialViewResult与ViewResult非常相似,通过用在前端为Ajax应用程序的情况下,并可以通过Ajax来取得网页中的部分内容。
public ActionResult About() { return PartialView(); }
4.3 EmptyResult
有一些Action在执行后其实不需要返回任何数据,例如一个页面执行完后直接转到其他页面的情况。EmptyResult不会执行任何响应客户端的程序,所以也不会返回任何数据。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public ActionResult Empty() { return new EmptyResult(); } } }
或
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public void Empty() { return; } } }
public EmptyResult Index() { return new EmptyResult(); }
使用EmptyResult与Response.RedirectPermanent()进行HTTP301跳转
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public void Redirect() { Response.RedirectPermanent("/Home/Index"); } } }
public RedirectResult About() { return Redirect("/Home/Index"); }
4.4 ContentResult
ContentResult类可以响应文字内容的结果。可以让ContentResult类响应任意指定文字内容、Content-Type和文字编码(Encoding)。
示例响应一段XML文字,并设定响应的Content-Type为text/xml,文本编码格式为Encoding.UTF8.
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public ActionResult Content() { return Content("<root><text>123</text></root>", "text/xml", System.Text.Encoding.UTF8); } } }
响应HTML字符串
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public ActionResult Content() { string strHTML = "<h1>123</h1>"; return Content(strHTML); } } }
ASP.NET MVC会进行判断,只要Action返回的不是ActionResult类,就会将返回的类转换成字符串输出。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Libing.Portal.Web.Controllers { public class HomeController : Controller { public string Content() { string strHTML = "<h1>123</h1>"; return strHTML; } } }
6.5 FileResult
FileResult类可以响应任意的文件内容,包括二进制格式的数据,可以输入byte[]、文件路径、Stream数据、Content-Type、下载文件名等参数并将其返回客户端。
FileResult是一个抽象类,在ASP.NET MVC中实现FileResult类的子类包括:
◊ FilePathResult:响应一个实体文件;
◊ FileContentResult:响应一个byte[]的内容;
◊ FileStreamResult:响应一个Stream数据。
示例:FilePathResult
public ActionResult Download() { return File(Server.MapPath("~/Content/Logo.png"), "image/png"); }
示例:FileContentResult
public ActionResult Download() { FileStream fs = new FileStream(Server.MapPath("~/Content/Logo.png"), FileMode.Open, FileAccess.Read); byte[] fileContent = new byte[Convert.ToInt32(fs.Length)]; fs.Read(fileContent, 0, Convert.ToInt32(fs.Length)); return File(fileContent, "image/png"); }
示例:FileStreamResult
public ActionResult Download() { FileStream fs = new FileStream(Server.MapPath("~/Content/Logo.png"), FileMode.Open, FileAccess.Read); return File(fs, "image/png"); }
示例:pdf文件
public ActionResult Download() { FileStream fs = new FileStream(Server.MapPath("~/Content/Report.pdf"), FileMode.Open, FileAccess.Read); byte[] fileContent = new byte[Convert.ToInt32(fs.Length)]; fs.Read(fileContent, 0, Convert.ToInt32(fs.Length)); return File(fileContent, "application/pdf", "Report.pdf"); }
示例:中文名称文件
public ActionResult Download() { FileStream fs = new FileStream(Server.MapPath("~/Content/Report.txt"), FileMode.Open, FileAccess.Read); byte[] fileContent = new byte[Convert.ToInt32(fs.Length)]; fs.Read(fileContent, 0, Convert.ToInt32(fs.Length)); return File(fileContent, "text/plain", Server.UrlPathEncode("报表.txt")); }
6.6 JavaScriptResult
JavaScriptResult类的用途是将JavaScript代码响应给浏览器。通过Ajax利用JavaScriptResult类来响应当前的JavaScript程序代码并将其提交到浏览器动态执行。
JavaScriptResult类的功能与ContentResult类主要差别在于JavaScriptResult类的默认Content-Type为application/x-javascript。
public ActionResult RunJavaScript() { return JavaScript("alert('运行JavaScript')"); }
@Ajax.ActionLink("测试JavaScript", "RunJavaScript", new AjaxOptions())
6.7 JsonResult
JSON(JavaScript Object Notation)是Web实现Ajax应用程序时经常使用的一种数据传输格式,JsonResult可以自动将任意对象的数据序列转换成JSON格式返回。JsonResult默认的Content-Type是application/json。
JsonResult使用JavaScriptSerializer完成JSON序列化,如果对象无法序列化,转换过程也会发生意外。为了避免JSON Hijacking攻击,ASP.NET MVC基于安全考虑,设置在默认情况下,任何以JsonResult类返回的请求都不允许GET方法从中获取JSON数据。要JsonResult对HTTP GET请求进行响应,需Json()方法设置JsonRequestBehavior.AllowGet。
示例:Json()默认
public ActionResult GetList() { List<Product> products = new List<Product>(); products.Add(new Product { ProductID = 1, ProductName = "ASP.NET MVC" }); return Json(new { root = products, totalProperty = products.Count }); }
<script type="text/javascript"> $(function () { $.post("@Url.Action("GetList","Home")", function (data) { console.log(data.totalProperty); }, "json" ); }); </script>
示例:Json() AllowGet
public ActionResult GetList() { List<Product> products = new List<Product>(); products.Add(new Product { ProductID = 1, ProductName = "ASP.NET MVC" }); return Json(new { root = products, totalProperty = products.Count }, JsonRequestBehavior.AllowGet); }
<script type="text/javascript"> $(function () { $.get("@Url.Action("GetList","Home")", function (data) { console.log(data.totalProperty); }, "json" ); }); </script>
6.8 RedirectResult
RedirectResult主要用于执行指向其他页面的重定向。
Redirect()方法定义:
protected internal virtual RedirectResult Redirect(string url);
示例:
public ActionResult Redirect() { return Redirect("/Home/Index"); }
6.9 RedirectToRoute
Controller类中有两个与RedirectToRoute类有关的辅助方法:RedirectToAction()和RedirectToRoute()。
6.9.1 RedirectToAction
1>. 原型定义
protected internal RedirectToRouteResult RedirectToAction(string actionName);
protected internal RedirectToRouteResult RedirectToAction(string actionName, string controllerName);
protected internal RedirectToRouteResult RedirectToAction(string actionName, string controllerName, object routeValues);
protected internal RedirectToRouteResult RedirectToAction(string actionName, object routeValues);
2>. 示例
public ActionResult About() { return RedirectToAction("Index"); }
return RedirectToAction("Index", "Home");
return RedirectToAction("List", "Home", new { page = 2 });
return RedirectToAction("Details", new { id = product.ProductID });
6.9.2 RedirectToRoute
1>. 原型定义
protected internal RedirectToRouteResult RedirectToRoute(object routeValues);
protected internal RedirectToRouteResult RedirectToRoute(string routeName);
protected internal RedirectToRouteResult RedirectToRoute(string routeName, object routeValues);
2>. 示例
public ActionResult About() { return RedirectToRoute(new { action = "Index" }); }
return RedirectToRoute(new { controller = "Home", action = "Index" });
return RedirectToRoute(new { controller = "Home", action = "Index", page = 2 });