溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

精通MVC3摘譯(7)-處理輸出(1)

發(fā)布時(shí)間:2020-06-21 12:13:07 來源:網(wǎng)絡(luò) 閱讀:696 作者:cnn237111 欄目:編程語言

處理輸出

controller完成處理請(qǐng)求后,通常需要生產(chǎn)響應(yīng)。當(dāng)我們直接實(shí)現(xiàn) IController 接口創(chuàng)建controller時(shí),我們就需要對(duì)處理請(qǐng)求的各個(gè)方面負(fù)責(zé),包括對(duì)客戶端的響應(yīng)。如果我們需要生成HTML響應(yīng)。比如,我們需要?jiǎng)?chuàng)建組合HTML數(shù)據(jù),并使用使用 Response.Write方法傳給客戶端。相似的,如果我們想給用戶瀏覽器返回另一個(gè)URL,我們需要調(diào)用Response.Redirect方法,直接傳遞URL。這些方法都在下面列出:

using System.Web.Mvc;

using System.Web.Routing;

namespace ControllersAndActions.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));

        // ... or ...

        requestContext.HttpContext.Response.Redirect("/Some/Other/Url");

        }

    }

}

當(dāng)你從Controller類中繼承了一個(gè)controller,你就使用相同的方法。當(dāng)你通過Controller.Response屬性,在Execute方法鮮中讀取requestContext.HttpContext.Response屬性時(shí),你得到的返回值是HttpResponseBase類。如下:

using System.Web.Mvc;

namespace ControllersAndActions.Controllers {

    public class DerivedController : Controller {

public void Index() {

string controller = (string)RouteData.Values["controller"];

string action = (string)RouteData.Values["action"];

Response.Write(

string.Format("Controller: {0}, Action: {1}", controller, action));

// ... or ...

Response.Redirect("/Some/Other/Url");

}

    }

}

This approach works, but it has a few problems:

這個(gè)方法也是可行的,但是有幾個(gè)小問題:

controller類必須包含HTML或者URL結(jié)構(gòu)的詳細(xì)信息。這就讓類的可讀性和可維護(hù)性變差。

對(duì)controller單元測(cè)試變的困難,你需要?jiǎng)?chuàng)建模擬的Response信息,使之能從controller接受并處理輸出,這意味著要轉(zhuǎn)換HTML關(guān)鍵字,這都是很痛苦的過程。

對(duì)每個(gè)請(qǐng)求都用這種方法處理非常乏味,而且容易出錯(cuò)。一些程序員喜歡絕對(duì)控制,喜歡創(chuàng)建一個(gè)未處理過的controller,但是大多數(shù)程序員對(duì)這種方法很不習(xí)慣。

幸運(yùn)的是,MVC Framework能很好的處理這些問題,這個(gè)功能叫做action results。下面會(huì)介紹action result的概念,并展示幾種不同的從controller生成響應(yīng)的方法。

理解Action Results

MVC并不直接和Response對(duì)象交互,而是返回一個(gè)ActionResult類的子類,以此描述我們想從controller中得到的響應(yīng),比如呈現(xiàn)視圖或者跳轉(zhuǎn)到URL或者另一個(gè)action方法。

注意,action result系統(tǒng)只是command模式的一個(gè)實(shí)例。更多信息,看http://en.wikipedia.org/wiki/Command pattern。

當(dāng)MVC Framework從action方法中收到一個(gè)ActionResult對(duì)象,它會(huì)調(diào)用這個(gè)類所定義的ExecuteResult方法。這個(gè)action result就會(huì)處理response對(duì)象。生成符合你意圖的輸出。一個(gè)簡(jiǎn)單的關(guān)于RedirectResult 類的例子。如下。MVC Framework開源的一個(gè)好處是,你可以看到背后的工作方式。我們簡(jiǎn)化了這個(gè)類,使之容易讀懂。

public class RedirectResult : ActionResult {

public RedirectResult(string url): this(url, permanent: false) {

}

public RedirectResult(string url, bool permanent) {

Permanent = permanent;

Url = url;

}

public bool Permanent {

get;

private set;

}

public string Url {

get;

private set;

}

public override void ExecuteResult(ControllerContext context) {

string destinationUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext);

if (Permanent) {

context.HttpContext.Response.RedirectPermanent(destinationUrl,

endResponse: false);

}

else {

context.HttpContext.Response.Redirect(destinationUrl, endResponse: false);

}

}

}

當(dāng)我們創(chuàng)建一個(gè)RedirectResult類的實(shí)例時(shí),我們傳入要定位給用戶的URL。 MVC Framework在action方法完成后,會(huì)執(zhí)行ExecuteResult方法,通過framework提供方的 ControllerContext 對(duì)象得到query的response對(duì)象,同時(shí)調(diào)用RedirectPermanent方法或者Redirect方法。

我們可以通過創(chuàng)建一個(gè)新的RedirectResult實(shí)例,并且從action方法返回它。如下代碼,展示了DerivedController類有2個(gè)action方法,其中之一使用了RedirectResult來重定向請(qǐng)求。

using System.Web.Mvc;

namespace ControllersAndActions.Controllers {

public class DerivedController : Controller {

public void Index() {

        string controller = (string)RouteData.Values["controller"];

string action = (string)RouteData.Values["action"];

Response.Write(

string.Format("Controller: {0}, Action: {1}", controller, action));

}

public ActionResult Redirect() {

return new RedirectResult("/Derived/Index");

}

}

}

如果你導(dǎo)航到 /Derived/Redirect,瀏覽器會(huì)重定位到/Derived/Index。為了是代碼更簡(jiǎn)潔,Controller類提供簡(jiǎn)單的方法來生成不同的ActionResults,比如,我們可以通過返回Redirect方法的結(jié)果,實(shí)現(xiàn)同樣的效果。

public ActionResult Redirect() {

return Redirect("/Derived/Index");

}

這對(duì)復(fù)雜的action result來說沒有什么復(fù)雜的,但是你卻能寫出簡(jiǎn)潔一致的代碼。你也可以很方便的對(duì)你的action方法做單元測(cè)試。MVC Framework包含了很多內(nèi)建的action result類型,在下面列出,這些類型都繼承自ActionResult,而且大多使用起來都很簡(jiǎn)單。

精通MVC3摘譯(7)-處理輸出(1)精通MVC3摘譯(7)-處理輸出(1)

通過呈現(xiàn)View來返回HTML

最常用的響應(yīng)是要從action方法中生成一個(gè)HTML,發(fā)送給瀏覽器。當(dāng)使用action result系統(tǒng),你通過創(chuàng)建ViewResult實(shí)例來指定想要生成的HTML。如下演示代碼

using System.Web.Mvc;

namespace ControllersAndActions.Controllers {

public class ExampleController : Controller {

public ViewResult Index() {

    return View("Homepage");

    }

    }

}

這些代碼,使用View方法創(chuàng)建了ViewResult類的實(shí)例,該實(shí)例作為action方法的結(jié)果返回。

注意,返回類型是ViewResult,如果把返回值設(shè)為ActionResult,那么此方法也會(huì)編譯運(yùn)行的很好。事實(shí)上,一些MVC程序員喜歡吧每一個(gè)action的返回值都定義成ActionResult,即使他們知道返回的是一個(gè)特定的類型。在此,我們偏向于只要知道該返回的是什么類型,我們就使用這個(gè)返回類型。在下面的例子中我們都會(huì)這樣做,這會(huì)讓你清楚的知道返回的是什么類型的值。

這個(gè)例子中,我們指定了想要呈現(xiàn)的view,在這個(gè)例子中,我們指定的是Homepage view。

注意,我們可以顯式的創(chuàng)建ViewResult對(duì)象,(返回new ViewResult { ViewName ="Homepage" };)這是一個(gè)完美的可行的方法,但是我們哈市偏向使用Controller類中定義的簡(jiǎn)便方法。

當(dāng)MVC調(diào)用ViewResult對(duì)象的ExecuteResult方法,在指定的view上開始一個(gè)搜索。如果你項(xiàng)目中使用了area,那么framework會(huì)查詢下面幾個(gè)地址:

/Areas/<AreaName>/Views/<ControllerName>/<ViewName>.aspx

/Areas/<AreaName>/Views/<ControllerName>/<ViewName>.ascx

/Areas/<AreaName>/Views/Shared/<ViewName>.aspx

/Areas/<AreaName>/Views/Shared/<ViewName>.ascx

/Areas/<AreaName>/Views/<ControllerName>/<ViewName>.cshtml

/Areas/<AreaName>/Views/<ControllerName>/<ViewName>.vbhtml

/Areas/<AreaName>/Views/Shared/<ViewName>.cshtml

/Areas/<AreaName>/Views/Shared/<ViewName>.vbhtml

你可以看到,framework查詢的序列中有ASPX視圖引擎創(chuàng)建的view,即使我們指定了Razor。Framework有人會(huì)查詢C#和Visual Basic.NET Razor模板。MVC Framework會(huì)依次檢查這些文件是否存在,只要有一個(gè)匹配了,就會(huì)使用這個(gè)view作為action方法的結(jié)果來呈現(xiàn)。

如果你沒有使用area,或者你使用了area但是要呈現(xiàn)的文件不在上述清單中,那么framework會(huì)使用下面的地址繼續(xù)查詢“

/Views/<ControllerName>/<ViewName>.aspx

/Views/<ControllerName>/<ViewName>.ascx

/Views/Shared/<ViewName>.aspx

/Views/Shared/<ViewName>.ascx

/Views/<ControllerName>/<ViewName>.cshtml

/Views/<ControllerName>/<ViewName>.vbhtml

/Views/Shared/<ViewName>.cshtml

/Views/Shared/<ViewName>.vbhtml

同樣的,只要MVC找到一個(gè)匹配項(xiàng),就停止搜尋,這個(gè)找到的view就作為對(duì)客戶端的響應(yīng)。

MVC Framework查找目錄順序也是一個(gè)約定的配置,你不需要注冊(cè)view文件。你只需要把它們放在正確的地方,framework會(huì)找到它們的。防止view的這種約定也是可以配置的,在后續(xù)會(huì)講到。

我們可以在更進(jìn)一步,在調(diào)用view方法時(shí),忽略掉想要呈現(xiàn)的view的名字。如下代碼

using System.Web.Mvc;

namespace ControllersAndActions.Controllers {

public class ExampleController : Controller {

public ViewResult Index() {

return View();

}

}

}

當(dāng)我我們這么做的時(shí)候,MVC Framework假設(shè)我們需要呈現(xiàn)的view和action方法的名字是一致的。意思就,上例中的View方法的調(diào)用會(huì)開始查詢命名為Index的視圖。注意,這樣做的結(jié)果就是MVC Framework會(huì)尋找和action方法同名的view,但是view的名字事實(shí)上由RouteData.Values["action"]的值決定。

View 有多個(gè)重載方法,分別可以在創(chuàng)建的ViewResult對(duì)象屬性上設(shè)置不同的值。比如,你可以顯式的覆蓋view的laout屬性,如下:

public ViewResult Index() {

return View("Index", "_AlternateLayoutPage");

}

使用view的路徑設(shè)置view

命名約定的方法非常簡(jiǎn)潔,但是限制了你能呈現(xiàn)的view。如果你想要呈現(xiàn)一個(gè)指定的view,你可以顯式的輸入路徑。如下:

using System.Web.Mvc;

namespace ControllersAndActions.Controllers {

public class ExampleController : Controller {

public ViewResult Index() {

return View("~/Views/Other/Index.cshtml");

}

}

}

當(dāng)你如上那樣設(shè)定了view,路徑必須以/或者~/開頭,而且必須包含文件擴(kuò)展名,比如cshtml。

從action方法中傳值給view

我們經(jīng)常會(huì)從action方法中傳數(shù)據(jù)給view。 MVC Framework提供很多方法來實(shí)現(xiàn)這種功能。這里我們會(huì)討論一下,在后續(xù)我們還會(huì)深入討論。

提供View Model對(duì)象

你可以通過View方法的參數(shù)傳遞對(duì)象給view,如下代碼:

public ViewResult Index() {

DateTime date = DateTime.Now;

return View(date);

}

我們傳遞了一個(gè)DateTime對(duì)象作為view model。我們可以在view中,使用Razor Model關(guān)鍵字,訪問這個(gè)對(duì)象,如下:

@{

ViewBag.Title = "Index";

}

<h3>Index</h3>

The day is: @(((DateTime)Model).DayOfWeek)

上述例子的view是無類型的或者弱類型的。view不知道任何關(guān)于view model對(duì)象的事情,它以object的實(shí)例來處理這model。(此處譯者測(cè)試下來,并不是object類型,而是dynamic類型,不知是為什么)要得到DayOfWeek屬性,必須轉(zhuǎn)換object類型到DateTime。這雖然可行,但是有點(diǎn)麻煩。我們可以通過強(qiáng)類型view使代碼簡(jiǎn)潔點(diǎn),我們告訴view,它的view model的類型是什么。如下代碼:

@model DateTime

@{

ViewBag.Title = "Index";

}

<h3>Index</h3>

The day is: @Model.DayOfWeek

我們使用了Razor的model關(guān)鍵字指定了view model的類型,注意當(dāng)我們指定model類型的時(shí)候,使用了一個(gè)小寫的m,而讀取值的時(shí)候用的是大寫的M。這不僅是我們的的代碼證件,也使得Visual Studio在強(qiáng)類型view中支持智能提示。如下:

精通MVC3摘譯(7)-處理輸出(1)

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI