Asp.Net MVC系列--進階篇之controller(1)
通過實現介面IController完成一個controller
對於預設的路由:
routes.MapRoute(
name: "Default",
url:"{controller}/{action}/{id}",
defaults: new { controller ="Home", action = "Index", id = UrlParameter.Optional }
);
新增controller:
public void Execute(RequestContextrequestContext)
{
var controller = (string)requestContext.RouteData.Values["controller"];
var action =(string)requestContext.RouteData.Values["action"];
requestContext.HttpContext.Response.Write(
string.Format("Controller: {0}, Action: {1}", controller,action));
}
訪問controller檢視結果:
這是最簡單的controller建立方式,但是通常不這樣做,因為:
我們拿到的是RequestContext物件,需要手動去生成html寫到Response裡面返回客戶端,程式碼將很難維護。
整合Controller類完成一個controller
一般的,每當我們新建一個controller,都是自動繼承controller類,這個類主要幫我們完成兩件事情:
1.會從路由拿到requestContext物件,解析出action以及引數,並呼叫
2.提供不同的result(command模式),返回給客戶端
另外,我們還可以使用filter,完成不同的crosscutting的concern,後面章節會詳細介紹。
由於引入了action和result的概念,使得我們的程式碼更容易單元測試,起碼比我們自己繼承IController介面,直接操作RequestContext物件容易很多。
controller示例:
public class DerivedController :Controller {
public ActionResult Index() {
ViewBag.Message = "Hellofrom the DerivedController Index method";
return View("MyView");
}
}
View程式碼:
@{
ViewBag.Title ="MyView";
}
<h2>MyView</h2>
Message: @ViewBag.Message
程式碼很簡單,就是用Viewbag傳值到View顯示出來,Controller返回了最常用的result,ViewResult。
從controller獲取客戶端傳值的方式
1.從context object 直接提取
2.通過引數傳進來(由基類controller完成解析)
3.通過model binding
context object常用的物件
Request.QueryString |
從Get 請求的url中取 |
Request.Form |
從Post請求的表單取 |
Request.Cookies |
把值放在請求的cookie裡帶過來 |
RouteData.Route |
從路由表裡取註冊的路由名 |
RouteData.Values |
從路由表獲取路由配置的匿名物件 |
HttpContext.Cache |
應用程式快取 |
HttpContext.Items |
儲存一些值,只在同一請求中使用(可以在httppipeline過程的不同module,handler,以及頁面傳遞值) |
HttpContext.Session |
當前使用者的session |
TempData |
存一些臨時值,取出後會被自動刪除 |
另外,不建議直接從RouteData.Values直接取傳來的引數值:
public ActionResult ShowWeatherForecast() {
string city =(string)RouteData.Values["city"];
DateTime forDate =DateTime.Parse(Request.Form["forDate"]);
return View(forDate);
}
建議改寫為傳參:
public ActionResult ShowWeatherForecast(string city, DateTime forDate) {
return View(forDate);
}
關於傳參,注意:
1.對於引用型別,如果RouteData沒有拿到引數,那麼就給null了,如果要避免接收null,可以使用預設引數
2.對於值型別,如果沒有拿到引數,就會丟擲異常,因此,建議值型別總提供預設引數,或者使用Nullable型別
例如:
public ActionResult Search(stringquery= "all", int page = 1) {
// ...process request...
return View();
}
使用Execute Result
Controller的職責:
1.操作domain model
2.返回一個合適的result
操作完domainmodel之後,就要給客戶端返回result了,不推薦手動去實現IController介面進行Redirect或者直接Response.Write資料給客戶端。前面說過了:
1.直接輸出html,或者直接跳轉url,降低了可讀性和可維護性
2.很難單元測試
3.交接很難上手
使用ActionResult
MVC Framework 的controller已經給我們了足夠的result型別來返回給客戶端完成互動。為了瞭解ActionResult,先customize一個:
public class CustomRedirectResult: ActionResult {
public string Url { get; set; }
public override void ExecuteResult(ControllerContextcontext) {
string fullUrl =UrlHelper.GenerateContentUrl(Url, context.HttpContext);
context.HttpContext.Response.Redirect(fullUrl);
}
}
要customize一個result,需要繼承ActionResult,主要實現ExecuteResult方法,MVCFramework給我們了一個controllerContext物件,裡面有足夠我們需要的資訊,以上建立的actionResult功能:指定一個url,拿到controllerContext物件生成一個fullurl,完成跳轉。
使用這個result:
public ActionResult ProduceOutput() {
if (Server.MachineName == "IORI"){
return new CustomRedirectResult {Url = "/Basic/Index" };
} else {
Response.Write("Controller:Derived, Action: ProduceOutput");
return null;
}
}
常用的result:
ViewResult |
返回一個view,可以指定不同的controller |
ParcialViewResult |
返回部分view |
RedirectToActionResult |
轉到另一個action |
RedirectResult |
返回301或者302(permanent) |
JsonResult |
返回js最喜歡的json,常用,尤其當前段打算採用純js template,或者single page application |
FileResult |
檔案result |
ContentResult |
字串 |
HttpUnauthorizedResult |
401,通常,會自動跳轉到登陸頁面 |
HttpNotFoundResult |
404 |
返回viewResult時,查詢順序:
1./Views/<ControllerName>/<ViewName>.aspx
2./Views/<ControllerName>/<ViewName>.ascx
3./Views/Shared/<ViewName>.aspx
4./Views/Shared/<ViewName>.ascx
5./Views/<ControllerName>/<ViewName>.cshtml
6./Views/<ControllerName>/<ViewName>.vbhtml
7./Views/Shared/<ViewName>.cshtml
8./Views/Shared/<ViewName>.vbhtml
可以看到,mvcframework會先從熟悉的aspx和ascx找起
直接傳遞路徑,返回指定view
public ViewResult Index() {
return View("~/Views/Other/Index.cshtml");
}
如果出現類似以上的程式碼,請思考兩個問題:
想要跳轉到另一個action?可以考慮使用RedirectToAction
View是否放錯了位置?
Action傳值到View
Model Object
public ViewResult Index() {
DateTime date = DateTime.Now;
return View(date);
}
View中:
@model DateTime
@{
ViewBag.Title ="Index";
}
<h2>Index</h2>
The day is: @Model.DayOfWeek
ViewBag
public ViewResult Index() {
ViewBag.Message ="Hello";
ViewBag.Date = DateTime.Now;
return View();
}
View中:
@{
ViewBag.Title ="Index";
}
<h2>Index</h2>
The day is:@ViewBag.Date.DayOfWeek
<p />
The message is: @ViewBag.Message
ViewBag優點:
可以不需要定義型別直接傳遞,並且可以傳遞任意個物件
缺點:
錯誤總是執行時,由於是DynamicObject(實際是DynamicViewDataDictionary繼承自DynamicObject,因此是像其他functionlanguage語言一樣可以動態擴充套件的)
跳重定向到指定url
HttpStatusCode : 302(臨時重定向)
public RedirectResult Redirect(){
return Redirect("/Example/Index");
}
HttpStatusCode:301 (永久重定向,使用小心,不常用)
public RedirectResult Redirect(){
return RedirectPermanent("/Example/Index");
}
跳轉回route
public RedirectToRouteResult Redirect() {
return RedirectToRoute(new {
controller = "Example",
action = "Index",
ID = "MyID"
});
}
大多數情況,遇到處理不掉的請求,我們起碼是可以確定跳轉到哪個controller和action的:
public RedirectToRouteResult RedirectToRoute() {
return RedirectToAction("Index");
}
可以指定controller:
public RedirectToRouteResult Redirect() {
return RedirectToAction("Index", "Basic");
}
Redirection過程中傳值
在MVCframework中,理想選擇應該是使用TempData:
賦值:
public RedirectToRouteResult RedirectToRoute() {
TempData["Message"] ="Hello";
TempData["Date"] =DateTime.Now;
return RedirectToAction("Index");
}
取值:
public ViewResult Index() {
ViewBag.Message =TempData["Message"];
ViewBag.Date =TempData["Date"];
return View();
}
這個物件的好處是,取完就被標記為removable了,請求完畢會自動清掉。如果想取多次,那麼可以使用peek方法(但是還是建議最後一次取了清掉(用索引取)):
TempData.Peek("Date");
另外,筆者還推薦HttpRequest.Items,也是在httppipeline內傳值的一個不錯的選擇。
返回httpstatus code
404 (url 找不到):
public HttpStatusCodeResult StatusCode() {
return new HttpStatusCodeResult(404, "URL cannot be serviced");
}
401(訪問許可權受限):
public HttpStatusCodeResult StatusCode() {
return new HttpUnauthorizedResult();
}
相關文章
- Asp.Net MVC4 系列--進階篇之Controller(2)ASP.NETMVCController
- Asp.Net MVC4 系列--進階篇之Model(1)ASP.NETMVC
- Asp.Net MVC4系列--進階篇之Helper(1)ASP.NETMVC
- Asp.Net MVC 系列--進階篇之FilterASP.NETMVCFilter
- Asp.Net MVC4系列--進階篇之AJAXASP.NETMVC
- Asp.Net MVC4 系列--進階篇之ViewASP.NETMVCView
- Asp.Net MVC4 系列-- 進階篇之路由(1)ASP.NETMVC路由
- Asp.Net MVC4 系列--進階篇之Model(2)ASP.NETMVC
- Asp.Net MVC4 系列--進階篇之Helper(2)ASP.NETMVC
- Asp.Net MVC4 系列--進階篇之路由 (2)ASP.NETMVC路由
- Asp.Net MVC4 系列--基礎篇(1)ASP.NETMVC
- Asp.net MVC – ControllerASP.NETMVCController
- [ASP.NET MVC 小牛之路]09 - Controller 和 Action (1)ASP.NETMVCController
- Asp.Net MVC 系列--基礎篇(2)ASP.NETMVC
- Asp.Net MVC系列--基礎篇(3)ASP.NETMVC
- 【webpack 系列】進階篇Web
- React進階篇1React
- Asp.Net MVC4系列---基礎篇(5)ASP.NETMVC
- Asp.Net MVC4系列---基礎篇(4)ASP.NETMVC
- asp.net mvc get controller name and action nameASP.NETMVCController
- ASP.NET MVC學習之模型驗證篇ASP.NETMVC模型
- ASP.NET MVC系列:AreaASP.NETMVC
- ASP.NET MVC系列:ModelASP.NETMVC
- ASP.NET MVC+EF框架+EasyUI實現許可權管理系列之開篇ASP.NETMVC框架UI
- QlikView Script – 進階篇1 Script呼叫Macro之變化ViewMac
- [ASP.NET MVC 小牛之路]10 - Controller 和 Action (2)ASP.NETMVCController
- 測開之函式進階· 第1篇《遞迴函式》函式遞迴
- ASP.NET MVC 之 AJAXASP.NETMVC
- ASP.NET MVC 使用 Datatables (1)ASP.NETMVC
- ASP.NET Core MVC 中的 [Controller] 和 [NonController]ASP.NETMVCController
- .NET進階系列之四:深入DataTable
- 帶你深度解鎖Webpack系列(進階篇)Web
- 正規表示式系列之中級進階篇
- asp.net core 系列之Response caching(1)ASP.NET
- Java多執行緒之進階篇Java執行緒
- Membership三步曲之進階篇
- 【第三篇】ASP.NET MVC快速入門之安全策略(MVC5+EF6)ASP.NETMVC
- Java進階篇 設計模式之十四 ----- 總結篇Java設計模式