九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
[ASP.NET MVC 小牛之路]09 - Controller 和 Action (1)

我們知道,在 MVC 中每個(gè)請(qǐng)求都會(huì)提交到 Controller 進(jìn)行處理。Controller 是和請(qǐng)求密切相關(guān)的,它包含了對(duì)請(qǐng)求的邏輯處理,能對(duì) Model 進(jìn)行操作并選擇 View 呈現(xiàn)給用戶,對(duì)于業(yè)務(wù)和數(shù)據(jù)的邏輯代碼以及接口和輔助類庫(kù)等一般都不放到 Controller 中。

Controller 和 Action 的內(nèi)容較多,我把它分成了兩篇,也可能會(huì)分成三篇。本篇介紹 Controller 的實(shí)現(xiàn)、Controller 對(duì)狀態(tài)數(shù)據(jù)的獲取、ActionResult 和 Action 的數(shù)據(jù)傳遞,后續(xù)將介紹 Controller 工廠、Action Invoker 和暫時(shí)還沒(méi)想好或正在學(xué)習(xí)的一些較高級(jí)的特性。

文目錄

繼承 IController 接口

在本系列前面的文章中,我們添加的 Controller 都是一個(gè)繼承自抽象類 System.Web.Mvc.Controller 的普通類(請(qǐng)注意:controller(或Controller) 和 Controller 類在本文是兩個(gè)意思,請(qǐng)?jiān)陂喿x本文時(shí)根據(jù)上下文理解)。Controller 抽象類封裝了很多很實(shí)用的功能,讓開(kāi)發(fā)人員不用自己去寫(xiě)那些重復(fù)煩瑣的處理代碼。

如果不使用封裝的 Controller 抽象類,我們也可以通過(guò)實(shí)現(xiàn) IController 接口來(lái)創(chuàng)建自己的 controller。IController 接口中只有一個(gè) Exctute 方法:

public interface IController {     void Execute(RequestContext requestContext); }

IController 接口在 System.Web.Mvc 命名空間下,一個(gè)結(jié)構(gòu)非常簡(jiǎn)單的接口。

當(dāng)請(qǐng)求送到一個(gè)實(shí)現(xiàn)了 IController 接口的 controller 類時(shí)(路由系統(tǒng)通過(guò)請(qǐng)求的URL能夠找到controller),Execute 方法被調(diào)用。

下面我們創(chuàng)建一個(gè)空的 MVC 應(yīng)用程序,在 Controllers 文件夾下添加一個(gè)實(shí)現(xiàn)了 IController 的類,并做一些簡(jiǎn)單的操作,如下:

using System.Web.Mvc;using System.Web.Routing;namespace MvcApplication1.Controllers {    public class BasicController : IController {                public void Execute(RequestContext requestContext) {                        string controller = (string)requestContext.RouteData.Values["controller"];            string action = (string)requestContext.RouteData.Values["action"];                        requestContext.HttpContext.Response.Write(                string.Format("Controller: {0}, Action: {1}", controller, action));        }    }}

運(yùn)行應(yīng)用程序,URL 定位到 /Basic/Index(你可以把 Index 改成其他任意片段名稱),結(jié)果如下:

實(shí)現(xiàn)了 IController 的類,MVC就會(huì)辨識(shí)它為一個(gè) controller 類,根據(jù) controller 名把對(duì)應(yīng)的請(qǐng)求交給這個(gè)類處理。

但對(duì)于一個(gè)稍稍復(fù)雜的應(yīng)用程序,自己實(shí)現(xiàn) IController 接口是要做很多工作的,我們很少會(huì)這么做。通過(guò)這我們更好地理解了 controller 的運(yùn)行,controller 中一切對(duì)請(qǐng)求的處理都是從 Execute 方法開(kāi)始的。

繼承 Controller 抽象類

MVC 允許我們自由地進(jìn)行自定義和擴(kuò)展,比如像上面講的你可以實(shí)現(xiàn) IController 接口來(lái)創(chuàng)建對(duì)各類請(qǐng)求的各種處理并生成結(jié)果。不喜歡 Action 方法或不關(guān)心 View,那么你可以自己動(dòng)手寫(xiě)一個(gè)更好更快更優(yōu)雅的 controller 來(lái)處理請(qǐng)求。但像前面說(shuō)的,自己實(shí)現(xiàn) IController 接口要做很多工作,最重要的是沒(méi)有經(jīng)過(guò)長(zhǎng)期實(shí)踐測(cè)試,代碼的健壯性得不到保證, 一般不建議你這么做。MVC 框架的 System.Web.Mvc.Controller 類,提供了足夠?qū)嵱玫奶匦詠?lái)方便我們對(duì)請(qǐng)求的處理和返回結(jié)果。

繼承 Controller 類的 controller 我們已經(jīng)使用過(guò)很多次了,對(duì)它已經(jīng)有一定的了解,它提供了如下幾個(gè)關(guān)鍵的特性:

  • Action方法:一個(gè) Controller,它的行為被分為多個(gè)方法,通常一個(gè)方法對(duì)應(yīng)著一個(gè)請(qǐng)求,并且可以通過(guò)方法參數(shù)來(lái)取得請(qǐng)求傳遞過(guò)來(lái)的數(shù)據(jù)。
  • ActionResult:可以返回一個(gè)描述了 Action 方法執(zhí)行結(jié)果的對(duì)象,這樣的好處是想返回什么結(jié)果就指定對(duì)應(yīng)的返回對(duì)象就行,不用關(guān)心怎么去執(zhí)行并生成結(jié)果。
  • Filters:通過(guò)C#特性,對(duì)某一種行為的處理(比如授權(quán)和驗(yàn)證)進(jìn)行封裝,方便了在多個(gè) Controller 和 Action 方法之間進(jìn)行重用。

所以,如果你不是因?yàn)樘厥獾男枨蠡蜷e得蛋疼,創(chuàng)建一個(gè)滿足要求的 Controller 最好的途徑是繼承 Controller 抽象類。由于之前我們已經(jīng)使用過(guò)多次,這里就不再進(jìn)行具體的演示了,但我們還是來(lái)看一下它的代碼結(jié)構(gòu)。

在 Controllers 文件夾下添加一個(gè) Controller,VS 已經(jīng)把類的結(jié)構(gòu)幫我們生成好了,如果你喜歡整潔,會(huì)習(xí)慣性地把不需要用到的引用刪掉,代碼如下:

using System.Web.Mvc;namespace MvcApplication1.Controllers {        public class DerivedController : Controller {                public ActionResult Index() {            ViewBag.Message = "Hello from the DerivedController Index method";            return View("MyView");        }    }}

我們可以查看 Controller 抽象類的定義,發(fā)現(xiàn)它是繼承 ControllerBase 類的,在 ControllerBase 類中實(shí)現(xiàn)了 IController 接口的 Execute 方法,這個(gè)方法是MVC對(duì)請(qǐng)求進(jìn)行處理的各個(gè)組件的入口,其中包括通過(guò)路由系統(tǒng)找到 Action 方法并調(diào)用。

Controller 類內(nèi)部使用 Razor 視圖系統(tǒng)來(lái)呈現(xiàn) View,這里通過(guò) View 方法,指定 View 的名稱參數(shù)來(lái)告訴 MVC 選擇 MyView 視圖來(lái)返回給用戶結(jié)果。

在 Controller 中獲取狀態(tài)數(shù)據(jù)

我們經(jīng)常需要訪問(wèn)客戶端提交過(guò)來(lái)的數(shù)據(jù),比如 QueryString 值、表單值和通過(guò)路由系統(tǒng)來(lái)自 URL 的參數(shù)值,這些值都可稱為狀態(tài)數(shù)據(jù)。下面是 Controller 中獲取狀態(tài)數(shù)據(jù)的三個(gè)主要來(lái)源:

  • 一系列的上下文對(duì)象。
  • 傳遞給 Action 方法的參數(shù)。
  • 顯式的調(diào)用框架的模型綁定(Model Binding)特性。

從上下文對(duì)象中獲取狀態(tài)數(shù)據(jù)

獲取狀態(tài)數(shù)據(jù)最直接的方法就是從上下文對(duì)象中提取。當(dāng)你創(chuàng)建了一個(gè)繼承自 Controller 類的 Controller 時(shí),可以通過(guò)一系列的屬性可以方便的訪問(wèn)到和請(qǐng)求相關(guān)的數(shù)據(jù),這些屬性包括 Request、Response、RouteData、HttpContext 和 Server,每一個(gè)都提供了請(qǐng)求相關(guān)的不同類型的信息。下面列出了最常的上下文對(duì)象:

在 Action 方法中可以使用任意上下文對(duì)象來(lái)獲取請(qǐng)求相關(guān)的信息,如下面在 Action 方法中所演示的:

...public ActionResult RenameProduct() {    //訪問(wèn)不同的上下文對(duì)象    string userName = User.Identity.Name;    string serverName = Server.MachineName;    string clientIP = Request.UserHostAddress;    DateTime dateStamp = HttpContext.Timestamp;    AuditRequest(userName, serverName, clientIP, dateStamp, "Renaming product");                //從POST請(qǐng)求提交的表單中獲取數(shù)據(jù)    string oldProductName = Request.Form["OldName"];    string newProductName = Request.Form["NewName"];    bool result = AttemptProductRename(oldProductName, newProductName);    ViewData["RenameResult"] = result;    return View("ProductRenamed");}...

這些上下對(duì)象不用特意去記,用的時(shí)候,你可以通過(guò)VS的智能提示來(lái)了解這些上下文對(duì)象。

使用 Action 方法參數(shù)獲取狀態(tài)數(shù)據(jù)

在本系列的前面的文章中,我們已經(jīng)知識(shí)如何通過(guò) Action 參數(shù)來(lái)接收數(shù)據(jù),這種方法和上面的從上下文對(duì)象中獲取相比,它更為簡(jiǎn)潔明了。比如,我們有下面這樣一個(gè)使用上下文對(duì)象的 Action 方法:

public ActionResult ShowWeatherForecast() {    string city = (string)RouteData.Values["city"];    DateTime forDate = DateTime.Parse(Request.Form["forDate"]);    // do something ...     return View();}

我們可以像下面這樣使用 Action 方法參數(shù)來(lái)重寫(xiě)它:

public ActionResult ShowWeatherForecast(string city, DateTime forDate) {     // do something ...     return View(); }

它不僅易讀性強(qiáng),也方便進(jìn)行單元測(cè)試。

Action 方法的參數(shù)不允許使用 ref 和 out 參數(shù),這是沒(méi)有意義的。

MVC 框架通過(guò)檢查上下文對(duì)象來(lái)為 Action 方法的參數(shù)提供值,它的名稱是不區(qū)分大小寫(xiě)的,比如 Action 方法的 city 參數(shù)的值可以是通過(guò) Request.Form["City"] 來(lái)獲取的。

理解 Action 方法的參數(shù)是如何被賦值的

Controller 類通過(guò) MVC 框架的 value provider 和 model binder 組件來(lái)為 Action 方法獲取參數(shù)的值。

value provider 提供了一系列Controller中可以訪問(wèn)到的值,在內(nèi)部它通過(guò)從 Request.Form、Request.QueryString、Request.Files 和 RouteData.Values 等上下文對(duì)象中提取數(shù)據(jù)(鍵值集合),然后把數(shù)據(jù)傳遞給 model binder,model binder 試圖將這些數(shù)據(jù)與Action方法的參數(shù)進(jìn)行匹配。默認(rèn)的 model binder 可以創(chuàng)建和賦值給任何.NET類型對(duì)象參數(shù)(即 Action 方法的參數(shù)),包括集合和自定義的類型。

在這不對(duì) model binder 進(jìn)行介紹,我將在本系列的后續(xù)博文中對(duì)其進(jìn)行專門(mén)的介紹。

理解 ActionResult

ActionResult 是描述 Action 方法執(zhí)行結(jié)果的對(duì)象,它的好處是想返回什么結(jié)果就指定對(duì)應(yīng)的返回對(duì)象就行,不用關(guān)心如何使用Response對(duì)象來(lái)組織和生成結(jié)果。ActionResult 是一個(gè)命令模式的例子,這種模式通過(guò)存儲(chǔ)和傳遞對(duì)象來(lái)描述操作。

當(dāng) MVC 框架從 Action 方法中接收到一個(gè) ActionResult 對(duì)象,它調(diào)用這個(gè)對(duì)象的 ExecuteResult 方法,其內(nèi)部是通過(guò) Response 對(duì)象來(lái)返回我們想要的輸出結(jié)果。

為了更好的理解,我們通過(guò)繼承 ActionResult 類來(lái)自定義一個(gè) ActionResult。在MVC工程中添加一個(gè)Infrastructure文件夾,在里面創(chuàng)建一個(gè)名為 CustomRedirectResult 的類文件,代碼如下:

using System.Web.Mvc;namespace MvcApplication1.Infrastructure {        public class CustomRedirectResult : ActionResult {                public string Url { get; set; }        public override void ExecuteResult(ControllerContext context) {            string fullUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext);            context.HttpContext.Response.Redirect(fullUrl);        }    }}

當(dāng)我們創(chuàng)建一個(gè) CustomRedirectResult 類的實(shí)例時(shí),我們可以傳遞想要跳轉(zhuǎn)的 URL。當(dāng) Action 方法執(zhí)行結(jié)束時(shí),MVC 框架調(diào)用 ExecuteResult 方法,ExecuteResult 方法通過(guò) ControllerContext 對(duì)象獲得 Response 對(duì)象,然后調(diào)用 Redirect 方法。

下面我們?cè)?Controller 中使用自定義的 CustomRedirectResult:

public class DerivedController : Controller {    ...    public ActionResult ProduceOutput() {        if (Server.MachineName == "WL-PC") {            return new CustomRedirectResult { Url = "/Basic/Index" };        }        else {            Response.Write("Controller: Derived, Action: ProduceOutput");            return null;        }    }}

運(yùn)行后我們看到如下結(jié)果:

當(dāng)運(yùn)行在本機(jī)(WL-PC)時(shí)直接重定向到了指定的/Basic/Index。

上面我們通過(guò)自定義 CustomRedirectResult 來(lái)實(shí)現(xiàn)重定向,我們可以用 MVC 框架提供的方法,如下:

... public ActionResult ProduceOutput() {     return new RedirectResult("/Basic/Index"); } 

為了使用方便,Controller 類中為大部分類型的 ActionResult 提供簡(jiǎn)便的方法,如上面的可像下面這樣簡(jiǎn)寫(xiě):

... public ActionResult ProduceOutput() {     return Redirect("/Basic/Index"); }

MVC框架包含了許多 ActionResult 類型,這些類型都繼承自 ActionResult 類,大部分在 Controller 類中都有簡(jiǎn)便的方法,下面列舉了一些:

除了該表列出來(lái)的,還有ContentResult、FileResultJsonResult JavaScriptResult。具體每種ActionResult類型的用法這里就不講了,大家可以看看蔣老師的了解ASP.NET MVC幾種ActionResult的本質(zhì)系列的文章。

幾種從 Action 傳遞數(shù)據(jù)到 View 的方式

我們經(jīng)常需要在 Action 方法中傳遞數(shù)據(jù)到一個(gè) View 中,MVC 框架為此提供了一些很方便的操作。下面簡(jiǎn)單簡(jiǎn)介幾種常用的方式。

View Model 對(duì)象

通過(guò) View Model 對(duì)象傳遞數(shù)據(jù)給View,這是最常用的一種,在 Acton 方法執(zhí)行結(jié)束時(shí)通過(guò) View 方法傳遞 View Model 對(duì)象給 View,如下代碼所示:

... public ViewResult Index() {     DateTime date = DateTime.Now;     return View(date); } 

在 View 中我們通過(guò) Model 屬性來(lái)使用傳遞過(guò)來(lái)的 View Model 對(duì)象,如下:

@model DateTime @{     ViewBag.Title = "Index"; }<h2>Index</h2> The day is: @Model.DayOfWeek

在 Razor 視圖引擎中,@model 的作用是聲明 odel 屬性的類型,省去了類型轉(zhuǎn)換的麻煩,而 @Model 是V iew Model 對(duì)象的引用。

ViewBag、ViewData 和 TempData 屬性

ViewBag、ViewData 和 TempData 都是 Controller 和 View 中能訪問(wèn)到的屬性,都是用來(lái)存儲(chǔ)小量的數(shù)據(jù),他們的區(qū)別如下:

  • ViewBag,是一個(gè)動(dòng)態(tài)(dynamic)的弱類型,在程序運(yùn)行的時(shí)候解析,是 MVC3 中新增的特性,只在當(dāng)前View有效。
  • ViewData,是一個(gè)字典集合,也是只在當(dāng)前View有效,性能比 ViewBag 高,但是使用的時(shí)候需要類型轉(zhuǎn)換。
  • TempData,也是字典集合,一般用于兩個(gè)請(qǐng)求之間臨時(shí)緩存內(nèi)容或頁(yè)面間傳遞消息,保存在 Session 中,使用完以后則從 Session 中被清除。

下面是三者使用的例子,先在 Controller 中分別用三者存儲(chǔ)小數(shù)據(jù):

public class DerivedController : Controller {    public ActionResult Index() {        ViewBag.DayOfWeek = DateTime.Now.DayOfWeek;        ViewData["DayOfMonth"] = DateTime.Now.Day;        return View();    }    public ActionResult ProduceOutput() {        TempData["Message"] = "Warning message from Derived Controller.";        return Redirect("/Home/Index");    }}

在 Views/Derived 目錄下的 Index.cshtml 中,取出 ViewBag 和 ViewData 中的存儲(chǔ)的數(shù)據(jù):

...Day of week from ViewBag: @ViewBag.DayOfWeek<p /> Day of month from ViewData: @ViewData["DayOfMonth"] 

在 Views/Home 目錄下的 Index.cshtml 中,取 TempData 中的數(shù)據(jù)如下:

...
@TempData["Message"]

當(dāng)請(qǐng)求 /Derived/ProduceOutput 時(shí),ProduceOutput 方法將一條消息存到 TempData 中,并跳轉(zhuǎn)到 /Home/Index。

下面是分別是將URL定位到 /Derived/Index 和 /Derived/ProduceOutput 時(shí)的結(jié)果:

一般在當(dāng)前 View 中使用 ViewBag 或 ViewData,在兩個(gè)請(qǐng)求之間傳遞臨時(shí)數(shù)據(jù)用 TempData。由于 TempData 被使用后即被釋放,所以如果要二次使用 TempData 中的數(shù)據(jù)就需要將其存到其他變量中。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Asp.net MVC 中的TempData對(duì)象的剖析
MVC3中 ViewBag、ViewData和TempData的使用和區(qū)別
成功MVC控制器向視圖傳值的4種方法
ASP.NET MVC4 入門(mén)之添加一個(gè)View
ASP.NET 控制器和動(dòng)作方法
.net MVC通俗易懂實(shí)例
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服