ASP.NET?MVC高效構建Web應用- 商品搜索 - 京東
控制器(Controllers)是一個協調視圖和模型直接關系的特殊類。它響應用戶輸入,與模型進行對話,并決定呈現哪個視圖(如果有的話)。在ASP.NET MVC中,這個類文件通常以后綴名Controller表示。讓我們從新建一個控制器類開始動手。
3.2.1? 新建項目添加控制器源文件
我們首先將新建一個MVC項目,后續內容就基于此項目逐漸新增內容展開講解。
【例3.1】添加一個新控制器
(1)打開VS,新建一個基于MVC的ASP.NET項目,項目名稱是test。
(2)我們從創建控制器類開始。在解決方案資源管理器中,右鍵單擊 Controllers文件夾,然后單擊“添加”,再單擊“控制器”,此時出現“添加已搭建基架的新項”,在該對話框上,我們單擊“MVC 5 控制器- 空”,如圖3-2所示。
圖3?2
然后單擊“添加”。將新控制器命名為“HelloWorldController”,如圖3-3所示。
圖3?3
然后單擊“添加”。此時,解決方案資源管理器將創建名為HelloWorldController.cs的新文件和一個新文件夾Views\HelloWorld,位置如圖3-4所示。
圖3?4
(3)在控制器中準備添加代碼。我們在解決方案資源管理器中雙擊打開控制器源文件HelloWorldController.cs,然后刪除類HelloWorldController下的Index函數,并添加兩個新函數,代碼如下:
public class HelloWorldController : Controller{// 訪問方式:/HelloWorldpublic string Index()?{return "This is my <b>default</b> action..."; //該字符串顯示在網頁上,<b>是粗體的意思}// 訪問方式:/HelloWorld/Welcome/public string Welcome(){return "This is the Welcome action method..."; //該字符串顯示在網頁上}}
我們新增的控制器名稱是HelloWorldController,第一個方法是Index,當我們訪問控制器(http://localhost:xxxx/HelloWorld)時候,將默認調用這個Index方法,此時它返回一個字符串,因此在網頁瀏覽器中能看到這個字符串。另外一個方法是Welcome,當我們在瀏覽器中訪問URL地址“http://localhost:xxxx/HelloWorld/Welcome”時,將調用該方法,該方法也是返回一個字符串,因此我們可以在瀏覽器中看到這個字符串。
(4)按ctrl+F5運行項目,然后在彈出的瀏覽器的地址欄中輸入“https://localhost:44308/HelloWorld”,此時就可以在頁面上看到方法Index中返回的字符串了,如圖3-5所示。
訪問https://localhost:44308/HelloWorld相當于訪問https://localhost:44308/HelloWorld/index,index可以省略不寫。可以看出,網頁上顯示的字符串正是Index方法中返回的字符串,而且返回的字符串中帶有的html標記<b></b>也起作用了,它的作用就是讓<b>和</b>之間的字符變粗體。接著,我們再在瀏覽器地址欄中輸入“https://localhost:44308/HelloWorld/Welcome”,此時將調用HelloWorldController控制器中的Welcome方法,該方法也是返回一個字符串,因此網頁上也能看到一個字符串,如圖3-6所示。
?????
可見結果正確。另外,在ASP.NET MVC中,默認情況下,路由解析是不區分大小寫的,因此我們在地址欄中把“HelloWorld/Welcome”全部寫成小寫,也是可以正常顯示網頁。如果需要讓MVC的路由匹配變得大小寫敏感,你可以通過在RouteConfig.cs中定義路由的時候使用正則表達式來實現,但通常沒有必要。
現在我們理解了,ASP.NET MVC 根據傳入 URL 調用不同的控制器類,并調用不同的操作方法(比如我們例子中的Index方法和Welcome方法)。
3.2.2? 基于路由為方法增加一個參數
至此,我們并沒有傳遞參數給Welcome方法,實際開發中,通常會在URL中傳遞一些數據給內部方法,那我們要傳數據給方法,URL如何寫呢?可以這樣寫:
/[Controller]/[ActionName]/[Parameters]
Controller表示控制器名稱,ActionName表示方法名稱,Parameters表示要傳給方法的參數,比如http://localhost:xxx/HelloWorld/Welcome/1,這個1就是可以傳給Welcome方法的參數。那為何可以這樣寫呢?這個url格式在哪里指定呢?我們可以打開App_Start/RouteConfig.cs文件查看路由格式,該函數如下:
public static void RegisterRoutes(RouteCollection routes){routes.IgnoreRoute("{resource}.axd/{*pathInfo}");routes.MapRoute(name: "Default",url: "{controller}/{action}/{id}",defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });}
原來是在這個自動生成的函數中規定了這樣的url格式,而且參數的名稱也規定了,即id。那么我們在方法中也要定義一個名稱為id的參數,然后就可以得到URL中的參數值了。
我們看url那一行,{id}處在參數的位置上,表示要傳給方法action的參數,我們只需要在。defaults表示如果URL中不寫具體的方法名稱,那么默認訪問的方法就是Home控制器中Index,而且參數是可選的(UrlParameter.Optional),也就是可以沒有,這樣我們運行應用程序但不提供任何 URL 段時,它默認為在上述代碼的defaults 節中指定的Home控制器和Index操作方法。注意:Home控制器是新建項目就默認生成的,我們手動添加的控制器是HelloWorld。
了解了格式后,我們趁熱打鐵,趕緊在Welcome方法中添加一個參數,代碼如下:
public string Welcome(int id){return HttpUtility.HtmlEncode("data from url:"+ id);}
我們要把參數id在網頁上顯示出來。HttpUtility.HtmlEncode用于將字符串轉換為HTML編碼格式的字符串,目的是為了保護應用程序免受惡意輸入(因為我們的程序通過URL接收輸入參數,所以要做好一定的防護),因此我們需要通過對字符串應用HTML 編碼以防在Web應用程序中受到腳本攻擊。
運行項目,然后在瀏覽器的地址欄中輸入URL:https://localhost:44308/HelloWorld/Welcome/100,回車后,網頁就出現了“data from url:100”,如圖3-7所示。
圖3-7
可以看到,參數100傳給了Welcome方法,然后在網頁上顯示出來,有興趣的朋友還可以改100為其他數字,都可以正確顯示出來。值得注意,Welcome方法中的參數名id必須和RegisterRoutes方法中{id}一致,如果Welcome方法中的參數名不是id,那就會出錯了。但如果Welcome方法中寫成了大寫ID,那是沒事的,結果照樣正確,說明此方法對大小寫不敏感。
有朋友可能會執拗,就偏要在Welcome方法中用其他參數名稱,咋辦?很簡單,在RegisterRoutes方法中,把{id}改為你想要的名稱,比如我們改為{age},那么我們在Welcome方法中就可以用age作為參數名了,我們馬上試試。修改RegisterRoutes方法如下:
public static void RegisterRoutes(RouteCollection routes){???routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//把兩處id改為ageroutes.MapRoute(name: "Default",url: "{controller}/{action}/{age}",?defaults: new { controller = "Home", action = "Index", age = UrlParameter.Optional });}
然后再修改Welcome方法如下:
public string Welcome(int age){return HttpUtility.HtmlEncode("data from url:"+ age);}
也就是把參數名改為了age,返回的字符串也用了age。
馬上運行項目,輸入URL:https://localhost:44308/HelloWorld/Welcome/66,運行結果如圖3-8所示。
圖3?8
運行正確,現在我們知道如何使用自己想用的參數名了,原來需要在注冊路由方法RegisterRoutes中修改一下。
3.2.3? 基于路由為方法增加多個參數
剛剛我們把URL上的參數傳遞給了方法Welcome,但我們只是傳遞了一個參數,現在我們來傳遞多個參數。首先我們要在路由配置文件RouteConfig.cs中添加一個新路由,添加代碼如下:
routes.MapRoute(name: "abc",url: "{controller}/{action}/{name}/{height}/{age}");
這里的路由名稱name隨便取,比如abc;最關鍵的是url,這里我們在{action}后面添加了3個參數,分別是name、height和age,它們將傳入方法Welcome中,因此接下來我們要為Welcome方法添加參數,打開HelloWorldController.cs,修改Welcome方法如下所示:
public string Welcome(string name,float height, int age = 10){return HttpUtility.HtmlEncode("Hello " + name + ", your height:"+height+" and age:"+age);}
馬上運行項目,輸入URL:https://localhost:44308/HelloWorld/Welcome/Tom/1.81/20,運行結果如圖3-9所示。
圖3-9
運行正確,我們把3個參數值都顯示出來了。現在,我們知道如何傳多個參數給方法了。
在路由配置文件RouteConfig.cs中,擁有2個條路由,一條是名為Default的路徑,另外一條是名為abc的路徑。我們可以按兩種url來訪問,但前提是要定義好和url參數對應的方法。比如現在按照Default中的url(url: "{controller}/{action}/{age}")方式來訪問就出錯了,輸入URL:https://localhost:44308/helloWorld/Welcome/22,運行結果如圖3-10所示。
這是因為Welcome需要3個參數呢,而我們在URL中就給了一個參數,所以報錯了。我們可以在HelloWorldController類中增加一個方法,使其擁有一個參數,代碼如下:
public string howold(int age){return HttpUtility.HtmlEncode("age:" + age);}
然后運行項目,輸入URL:https://localhost:44308/helloWorld/howold/22,運行結果如圖3-11所示。
???
運行正確。現在我們既可以輸入1個參數,也可以輸入3個參數給不同的方法了,兩種URL路徑都能使用到。
3.2.4? 不改變路由為方法增加多個參數
剛剛我們為了傳遞多個參數給方法,還特意添加了一條新路由,略顯繁瑣,其實也可以不新增路由來傳遞多個參數的。方法是通過查詢字符串。現在我們基于已經存在的路由Default,來為Welcome方法添加多個參數,目前Default路由是這樣的:
routes.MapRoute(name: "Default",url: "{controller}/{action}/{age}",defaults: new { controller = "Home", action = "Index", age = UrlParameter.Optional });
age已經是一個參數了,它所需要的URL如下:
http://localhost:xxx/HelloWorld/Welcome/20
現在,我們可以在1后面加問號(?),然后再加查詢字符串,比如:
http://localhost:xxx/HelloWorld/Welcome/20?name=Tom&height=1.81
“name=Tom&height=1.81”就是查詢字符串,name和height是參數名,必須和Welcome方法中的參數名相同,Tom和1.81是參數值,也就是傳給Welcome方法的實參。而Welcome方法目前的代碼是這樣的:
public string Welcome(string name,float height, int age = 10){return HttpUtility.HtmlEncode("Hello " + name + ", your height:"+height+" and age:"+age);}
正好3個參數,name和height對應查詢字符串中name和height,age對應Default路徑中url規定的age。運行項目,輸入URL:https://localhost:44308/helloWorld/Welcome/20?name=Alice&height=1.68,運行結果如圖3-12所示。
圖3-12
運行正確。通過查詢字符串的方式,我們即使不新增路由,也可以給方法傳遞多個參數值。不信的話,可以把路由abc刪除,結果依然正確。但要注意,查詢字符串會在URL中暴露參數名稱。
這個實例寫到這里該結束了,否則太長了。在整個實例中,控制器一直在執行 MVC的VC部分,即視圖和控制器的工作。控制器將直接返回 HTML。通常,人們不希望控制器直接返回 HTML,因為這會使代碼變得非常繁瑣。相反,我們通常使用單獨的視圖模板文件來幫助生成HTML響應,后續我們將實現這個效果。