目錄
Index
首頁 後端開發 C#.Net教程 [ASP.NET MVC 小牛之路]09 - Controller 與 Action (1)

[ASP.NET MVC 小牛之路]09 - Controller 與 Action (1)

Dec 30, 2016 pm 04:00 PM

[ASP.NET
MVC 小牛之路]09 - Controller 和 Action (1)

我們知道,在 MVC 中每個請求都會提交到 Controller 進行處理。 Controller 是和請求密切相關的,它包含了對請求的邏輯處理,能對Model 進行操作並選擇View 呈現給用戶,對於業務和數據的邏輯代碼以及接口和輔助類庫等一般都不放到Controller 中。

Controller 和 Action 的內容較多,我把它分成了兩篇,也可能會分成三篇。本篇介紹 Controller 的實作、Controller 對狀態資料的取得、ActionResult 和 Action 的資料傳遞,後續將介紹 Controller 工廠、Action Invoker 和暫時還沒想好或正在學習的一些較高階的功能。

本文目錄


繼承IController 介面

在本系列前面的文章中,我們新增的Controller 都是一個繼承自抽象類別System.Web.Mvc.Controller 的普通類別(請注意:controller(或抽象類別System.Web.Mvc.Controller 的普通類別(請注意:controller(或抽象類別System.Web.Mvc.Controller 的普通類別(請注意:controller或Controller) 和Controller 類別在本文是兩個意思,請在閱讀本文時根據上下文理解)。 Controller 抽象類別封裝了許多很實用的功能,讓開發人員不用自己寫那些重複煩瑣的處理程式碼。

如果不使用封裝的 Controller 抽象類,我們也可以透過實作 IController 介面來建立自己的 controller。 IController 介面中只有一個 Exctute 方法:

public interface IController { 
    void Execute(RequestContext requestContext); 
}
登入後複製

Controller 介面在 System.Web.Mvc 命名空間下,一個結構非常簡單的介面。

當請求送到一個實作了 IController 介面的 controller 類別時(路由系統透過要求的URL能夠找到controller),Execute 方法被呼叫。

下面我們創建一個空的MVC 應用程序,在Controllers 資料夾下添加一個實現了IController 的類,並做一些簡單的操作,如下:

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));
        }
    }
}
登入後複製

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

[ASP.NET MVC 小牛之路]09 - Controller 與 Action (1)

實現了IController 的類,MVC就會辨識它為一個controller 類,根據controller 名把對應的請求交給這個類處理。

但對於一個稍微複雜的應用程序,自己實作 IController 介面是要做很多工作的,我們很少會這麼做。透過這我們更了解 controller 的運行,controller 中一切對請求的處理都是從 Execute 方法開始的。


繼承 Controller 抽象類別

MVC 讓我們可以自由地進行自訂和擴展,例如像上面講的你可以實作 IController 介面來建立對各類別請求的各種處理並產生結果。不喜歡 Action 方法或不關心 View,那麼你可以自己動手寫一個更好更快更優雅的 controller 來處理請求。但像前面說的,自己實作 IController 介面要做很多工作,最重要的是沒有經過長期實踐測試,程式碼的健壯性得不到保證, 一般不建議你這麼做。 MVC 框架的 System.Web.Mvc.Controller 類,提供了足夠實用的特性來方便我們對請求的處理和傳回結果。

繼承Controller 類別的controller 我們已經使用過很多次了,對它已經有一定的了解,它提供瞭如下幾個關鍵的特性:

Action方法:一個Controller,它的行為被分為多個方法,通常一個方法對應一個請求,並且可以透過方法參數來取得請求傳遞過來的資料。
ActionResult:可以傳回一個描述了 Action 方法執行結果的對象,這樣的好處是想返回什麼結果就指定對應的回傳對象就行,不用關心怎麼去執行並產生結果。
Filters:透過C#特性,對某一種行為的處理(例如授權和驗證)進行封裝,方便了在多個 Controller 和 Action 方法之間進行重複使用。

所以,如果你不是因為特殊的需求或閒得蛋疼,創建一個滿足要求的 Controller 最好的途徑是繼承 Controller 抽象類別。由於之前我們已經使用過多次,這裡就不再進行具體的演示了,但我們還是來看看它的程式碼結構。

在 Controllers 資料夾下方新增一個 Controller,VS 已經把類別的結構幫我們生成好了,如果你喜歡整潔,會習慣性地把不需要用到的引用刪掉,程式碼如下:

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 抽象类的定义,发现它是继承 ControllerBase 类的,在 ControllerBase 类中实现了 IController 接口的 Execute 方法,这个方法是MVC对请求进行处理的各个组件的入口,其中包括通过路由系统找到 Action 方法并调用。

Controller 类内部使用 Razor 视图系统来呈现 View,这里通过 View 方法,指定 View 的名称参数来告诉 MVC 选择 MyView 视图来返回给用户结果。


在 Controller 中获取状态数据

我们经常需要访问客户端提交过来的数据,比如 QueryString 值、表单值和通过路由系统来自 URL 的参数值,这些值都可称为状态数据。下面是 Controller 中获取状态数据的三个主要来源:

一系列的上下文对象。
传递给 Action 方法的参数。
显式的调用框架的模型绑定(Model Binding)特性。

从上下文对象中获取状态数据

获取状态数据最直接的方法就是从上下文对象中提取。当你创建了一个继承自 Controller 类的 Controller 时,可以通过一系列的属性可以方便的访问到和请求相关的数据,这些属性包括 Request、Response、RouteData、HttpContext 和 Server,每一个都提供了请求相关的不同类型的信息。下面列出了最常的上下文对象:


[ASP.NET MVC 小牛之路]09 - Controller 與 Action (1)

在 Action 方法中可以使用任意上下文对象来获取请求相关的信息,如下面在 Action 方法中所演示的:

...
public ActionResult RenameProduct() {
    //访问不同的上下文对象
    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请求提交的表单中获取数据
    string oldProductName = Request.Form["OldName"];
    string newProductName = Request.Form["NewName"];
    bool result = AttemptProductRename(oldProductName, newProductName);

    ViewData["RenameResult"] = result;
    return View("ProductRenamed");
}
...
登入後複製

这些上下对象不用特意去记,用的时候,你可以通过VS的智能提示来了解这些上下文对象。

使用 Action 方法参数获取状态数据

在本系列的前面的文章中,我们已经知识如何通过 Action 参数来接收数据,这种方法和上面的从上下文对象中获取相比,它更为简洁明了。比如,我们有下面这样一个使用上下文对象的 Action 方法:

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

我们可以像下面这样使用 Action 方法参数来重写它:

public ActionResult ShowWeatherForecast(string city, DateTime forDate) { 
    // do something ... 
    return View(); 
}
登入後複製

它不仅易读性强,也方便进行单元测试。

Action 方法的参数不允许使用 ref 和 out 参数,这是没有意义的。

MVC 框架通过检查上下文对象来为 Action 方法的参数提供值,它的名称是不区分大小写的,比如 Action 方法的 city 参数的值可以是通过 Request.Form["City"] 来获取的。

理解 Action 方法的参数是如何被赋值的

Controller 类通过 MVC 框架的 value provider 和 model binder 组件来为 Action 方法获取参数的值。

value provider 提供了一系列Controller中可以访问到的值,在内部它通过从 Request.Form、Request.QueryString、Request.Files 和 RouteData.Values 等上下文对象中提取数据(键值集合),然后把数据传递给 model binder,model binder 试图将这些数据与Action方法的参数进行匹配。默认的 model binder 可以创建和赋值给任何.NET类型对象参数(即 Action 方法的参数),包括集合和自定义的类型。

在这不对 model binder 进行介绍,我将在本系列的后续博文中对其进行专门的介绍。


理解 ActionResult

ActionResult 是描述 Action 方法执行结果的对象,它的好处是想返回什么结果就指定对应的返回对象就行,不用关心如何使用Response对象来组织和生成结果。ActionResult 是一个命令模式的例子,这种模式通过存储和传递对象来描述操作。

当 MVC 框架从 Action 方法中接收到一个 ActionResult 对象,它调用这个对象的 ExecuteResult 方法,其内部是通过 Response 对象来返回我们想要的输出结果。

为了更好的理解,我们通过继承 ActionResult 类来自定义一个 ActionResult。在MVC工程中添加一个Infrastructure文件夹,在里面创建一个名为 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);
        }
    }
}
登入後複製

当我们创建一个 CustomRedirectResult 类的实例时,我们可以传递想要跳转的 URL。当 Action 方法执行结束时,MVC 框架调用 ExecuteResult 方法,ExecuteResult 方法通过 ControllerContext 对象获得 Response 对象,然后调用 Redirect 方法。

下面我们在 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;
        }
    }
登入後複製

运行后我们看到如下结果:

[ASP.NET MVC 小牛之路]09 - Controller 與 Action (1)

当运行在本机(WL-PC)时直接重定向到了指定的/Basic/Index。

上面我们通过自定义 CustomRedirectResult 来实现重定向,我们可以用 MVC 框架提供的方法,如下:

... 
public ActionResult ProduceOutput() { 
    return new RedirectResult("/Basic/Index"); 
}
登入後複製

为了使用方便,Controller 类中为大部分类型的 ActionResult 提供简便的方法,如上面的可像下面这样简写:

... 
public ActionResult ProduceOutput() { 
    return Redirect("/Basic/Index"); 
}
登入後複製

MVC框架包含了许多 ActionResult 类型,这些类型都继承自 ActionResult 类,大部分在 Controller 类中都有简便的方法,下面列举了一些:

[ASP.NET MVC 小牛之路]09 - Controller 與 Action (1)

除了该表列出来的,还有ContentResult、FileResult、JsonResult 和 JavaScriptResult。具体每种ActionResult类型的用法这里就不讲了,大家可以看看蒋老师的了解ASP.NET
MVC几种ActionResult的本质系列的文章。


几种从 Action 传递数据到 View 的方式

我们经常需要在 Action 方法中传递数据到一个 View 中,MVC 框架为此提供了一些很方便的操作。下面简单简介几种常用的方式。

View Model 对象

通过 View Model 对象传递数据给View,这是最常用的一种,在 Acton 方法执行结束时通过 View 方法传递 View Model 对象给 View,如下代码所示:

... 
public ViewResult Index() { 
    DateTime date = DateTime.Now; 
    return View(date); 
}
登入後複製

在 View 中我们通过 Model 属性来使用传递过来的 View Model 对象,如下:

@model DateTime 

@{ 
    ViewBag.Title = "Index"; 
}

<h2 id="Index">Index</h2> 
The day is: @Model.DayOfWeek
登入後複製

在 Razor 视图引擎中,@model 的作用是声明 odel 属性的类型,省去了类型转换的麻烦,而 @Model 是V iew Model 对象的引用。

ViewBag、ViewData 和 TempData 属性

ViewBag、ViewData 和 TempData 都是 Controller 和 View 中能访问到的属性,都是用来存储小量的数据,他们的区别如下:

ViewBag,是一个动态(dynamic)的弱类型,在程序运行的时候解析,是 MVC3 中新增的特性,只在当前View有效。
ViewData,是一个字典集合,也是只在当前View有效,性能比 ViewBag 高,但是使用的时候需要类型转换。
TempData,也是字典集合,一般用于两个请求之间临时缓存内容或页面间传递消息,保存在 Session 中,使用完以后则从 Session 中被清除。

下面是三者使用的例子,先在 Controller 中分别用三者存储小数据:

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 中的存储的数据:

...
Day of week from ViewBag: @ViewBag.DayOfWeek
<p /> 
Day of month from ViewData: @ViewData["DayOfMonth"]
登入後複製

在 Views/Home 目录下的 Index.cshtml 中,取 TempData 中的数据如下:

...
@TempData["Message"]
登入後複製

当请求 /Derived/ProduceOutput 时,ProduceOutput 方法将一条消息存到 TempData 中,并跳转到 /Home/Index。

下面是分别是将URL定位到 /Derived/Index 和 /Derived/ProduceOutput 时的结果:

[ASP.NET MVC 小牛之路]09 - Controller 與 Action (1)

[ASP.NET MVC 小牛之路]09 - Controller 與 Action (1)

一般在当前 View 中使用 ViewBag 或 ViewData,在两个请求之间传递临时数据用 TempData。由于 TempData 被使用后即被释放,所以如果要二次使用 TempData 中的数据就需要将其存到其他变量中。

 以上就是[ASP.NET MVC 小牛之路]09 - Controller 和 Action (1)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

PHP MVC 架構:建立面向未來的 Web 應用程式 PHP MVC 架構:建立面向未來的 Web 應用程式 Mar 03, 2024 am 09:01 AM

引言在當今快速發展的數位世界中,建立健壯、靈活且可維護的WEB應用程式至關重要。 PHPmvc架構提供了實現這一目標的理想解決方案。 MVC(模型-視圖-控制器)是一種廣泛使用的設計模式,可將應用程式的各個方面分離為獨立的元件。 MVC架構的基礎MVC架構的核心原理是分離關注點:模型:封裝應用程式的資料和業務邏輯。視圖:負責呈現資料並處理使用者互動。控制器:協調模型和視圖之間的交互,管理使用者請求和業務邏輯。 PHPMVC架構phpMVC架構遵循傳統MVC模式,但也引進了語言特定的功能。以下是PHPMVC

PHP MVC 架構的進階指南:解鎖進階功能 PHP MVC 架構的進階指南:解鎖進階功能 Mar 03, 2024 am 09:23 AM

mvc架構(模型-視圖-控制器)是PHP開發中最受歡迎的模式之一,因為它為組織程式碼和簡化WEB應用程式的開發提供了清晰的結構。雖然基本的MVC原理對於大多數Web應用程式來說已經足夠,但對於需要處理複雜資料或實現高級功能的應用程序,它存在一些限制。分離模型層分離模型層是高階MVC架構常見的技術。它涉及將模型類分解為較小的子類,每個子類專注於特定功能。例如,對於一個電子商務應用程序,您可以將主模型類別分解為訂單模型、產品模型和客戶模型。這種分離有助於提高程式碼的可維護性和可重複使用性。使用依賴注入依賴

揭開SpringMVC框架的成功:它為何廣受歡迎 揭開SpringMVC框架的成功:它為何廣受歡迎 Jan 24, 2024 am 08:39 AM

SpringMVC框架解密:為什麼它如此受歡迎,需要具體程式碼範例引言:在當今的軟體開發領域中,SpringMVC框架已經成為開發者非常喜愛的一種選擇。它是基於MVC架構模式的Web框架,提供了靈活、輕量、高效的開發方式。本文將深入探討SpringMVC框架的魅力所在,並透過具體的程式碼範例來展示其強大之處。一、SpringMVC框架的優勢靈活的配置方式Spr

如何使用PHP實作MVC模式 如何使用PHP實作MVC模式 Jun 07, 2023 pm 03:40 PM

MVC(Model-View-Controller)模式是一種常用的軟體設計模式,可以幫助開發人員更好地組織和管理程式碼。 MVC模式將應用程式分為三個部分:模型(Model)、視圖(View)和控制器(Controller),每個部分都有自己的角色和職責。在本文中,我們將討論如何使用PHP實作MVC模式。模型(Model)模型代表應用程式的資料和資料處理。通常,

如何在PHP8框架中實現可擴充的MVC架構 如何在PHP8框架中實現可擴充的MVC架構 Sep 11, 2023 pm 01:27 PM

如何在PHP8框架中實現可擴展的MVC架構引言:隨著互聯網的快速發展,越來越多的網站和應用程式採用了MVC(Model-View-Controller)架構模式。 MVC架構的主要目標是將應用程式的不同部分分開,以便提高程式碼的可維護性和可擴展性。在本文中,我們將介紹如何在PHP8框架中實現可擴充的MVC架構。一、了解MVC架構模式MVC架構模式是一種軟體設

PHP中如何使用MVC架構設計項目 PHP中如何使用MVC架構設計項目 Jun 27, 2023 pm 12:18 PM

在Web開發中,MVC(Model-View-Controller)是一種常用的架構模式,用於處理和管理應用程式的資料、使用者介面和控制邏輯。 PHP作為流行的Web開發語言,也可以藉助MVC架構設計和建構Web應用程式。本文將介紹如何在PHP中使用MVC架構設計項目,並說明其優點和注意事項。什麼是MVCMVC是一種軟體架構模式,通常用於Web應用程式中。 MV

PHP8框架開發MVC:初學者需要知道的重要概念與技巧 PHP8框架開發MVC:初學者需要知道的重要概念與技巧 Sep 11, 2023 am 09:43 AM

PHP8框架開發MVC:初學者需要知道的重要概念和技巧引言:隨著網路的快速發展,Web開發在當今的軟體開發產業中扮演著重要的角色。 PHP被廣泛用於Web開發,並且有許多成熟的框架可以幫助開發人員更有效率地建立應用程式。其中,MVC(Model-View-Controller)架構是最常見且廣泛使用的模式之一。本文將介紹初學者在使用PHP8框架開發MVC應用程

揭秘 PHP MVC 架構的秘密:讓你的網站飛起來 揭秘 PHP MVC 架構的秘密:讓你的網站飛起來 Mar 03, 2024 am 09:25 AM

模型-視圖-控制器(mvc)架構是一種強大的設計模式,用於建立可維護且可擴展的WEB應用程式。 PHPMVC架構將應用程式邏輯分解為三個不同的元件:模型:表示應用程式中的資料和業務邏輯。視圖:負責呈現資料給使用者。控制器:充當模型和視圖之間的橋樑,處理使用者請求並協調其他元件。 MVC架構的優點:程式碼分離:MVC將應用程式邏輯與表示層分離,提高了可維護性和可擴充性。可重複使用性:視圖和模型元件可以跨不同的應用程式重複使用,減少重複程式碼。效能優化:MVC架構允許快取視圖和模型結果,從而提高網站速度。測試友善:分離

See all articles