ASP.NET MVC Controllers and Actions
MVC應用程序里的URL請求是通過控制器Controller處理的,不管是請求視圖頁面的GET請求,還是傳遞數據到服務端處理的Post請求都是通過Controller來處理的,先看一個簡單的Controlller:
public class DerivedController : Controller { public ActionResult Index() { ViewBag.Message = "Hello from the DerivedController Index method"; //動態數據 return View("MyView"); //指定返回的View } }
是個DerivedController,那么對應處理的URL就是這樣的:localhost:1042/Derived/Index,並且Index這個Action指定了返回的視圖是MyView,而不是同名的Index視圖,那么就需要新建一個視圖MyView。在Index這個Action方法內右鍵 - 添加視圖 - MyView,或者在解決方案的Views目錄下新建一個Derived目錄,再右鍵 - 新建視圖 - MyView:
@{ ViewBag.Title = "MyView"; } <h2> MyView</h2> Message: @ViewBag.Message
直接Ctrl+F5運行程序瀏覽器定位到的url是:localhost:1042,看看路由的定義:
routes.MapRoute( "Default", // 路由名稱 "{controller}/{action}/{id}", // 帶有參數的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數默認值 );
注意路由的最后一行:new { controller = "Home", action = "Index", id = UrlParameter.Optional }
都給默認值了,那么URL:localhost:1042 其實就是:localhost:1042/Home/Index id是可選參數。
localhost:1042/Home/Index這個Url找的Controller自然是HomeController,Index對應的是HomeController下的Index這個Action,顯然沒有HoomeController,自然會報404錯。
解決方法:
1.把路由的默認值修改成:
new { controller = "Derived", action = "Index", id = UrlParameter.Optional }
2.在瀏覽器的url欄里手動輸入:localhost:1042/Derived/index
可以通過上下文對象Context取一些參數:
string userName = User.Identity.Name; string serverName = Server.MachineName; string clientIP = Request.UserHostAddress; DateTime dateStamp = HttpContext.Timestamp;
跟普通的WebForm里一樣,可以通過Request.Form接收傳遞過來的參數:
string oldProductName = Request.Form["OldName"]; string newProductName = Request.Form["NewName"];
取URL里/路由的參數:
string city = RouteData.Values["city"].ToString();
給Controller傳參:
public ActionResult ShowWeatherForecast(string city, DateTime forDate) { ViewBag.City = city; ViewBag.ForDate = forDate; return View(); }
對應的a標簽是這樣的:
@Html.ActionLink("查看天氣(傳參)", "ShowWeatherForecast", new { city = "北京", forDate = @DateTime.Now })
再添加對應的視圖:
@{ Layout = null; } 要查詢的是:@ViewBag.City 的天氣,查詢的時間是:@ViewBag.ForDate
運行下程序ShowWeatherForecast視圖就顯示了:
要查詢的是:北京 的天氣,查詢的時間是:2013/11/25 21:08:04
當然也可以不傳參但是提供默認值:
@Html.ActionLink("查看天氣(默認值) ", "ShowWeatherForecast", new { forDate = @DateTime.Now })
沒有傳city,看Controller:
public ActionResult ShowWeatherForecast(DateTime forDate, string city = "合肥") { ViewBag.City = city; ViewBag.ForDate = forDate; return View(); }
視圖顯示:
要查詢的是:合肥 的天氣,查詢的時間是:2013/11/25 21:16:35
默認值已經起作用了。
控制器里獲取路由數據:
public string Index() { string controller = (string)RouteData.Values["controller"]; string action = (string)RouteData.Values["action"]; return string.Format("Controller: {0}, Action: {1}", controller, action); }
自然瀏覽器就會顯示:Controller: Derived, Action: index
Action里實現跳轉:
public void Index() { Response.Redirect("/Derived/ShowWeatherForecast"); }
使用Response.Redirect實現跳轉還比較偏WebForm化,MVC里更應該這么跳轉:
public ActionResult Index() { return new RedirectResult("/Derived/ShowWeatherForecast"); }
之前都是類似的Action都是Return的View這里卻Return的卻是RedirectResult,這就得看方法的返回值了,方法的返回值是ActionResult,並不僅僅是ViewResult,可以理解為ActionResult是ViewResult和RedirectResult等等的基類。
這里甚至可以直接返回視圖文件的物理路徑:
return View("~/Views/Derived/ShowWeatherForecast.cshtml");
常用的Action返回值類型有:
跳轉到別的Action:
public RedirectToRouteResult Redirect() { return RedirectToAction("Index"); }
上面的方法是跳轉到當前Controller下的另外一個Action,如果要跳轉到別的Controller里的Action:
return RedirectToAction("Index", "MyController");
返回普通的Text數據:
public ContentResult Index() { string message = "This is plain text"; return Content(message, "text/plain", Encoding.Default); }
返回XML格式的數據:
public ContentResult XMLData() { StoryLink[] stories = GetAllStories(); XElement data = new XElement("StoryList", stories.Select(e => { return new XElement("Story", new XAttribute("title", e.Title), new XAttribute("description", e.Description), new XAttribute("link", e.Url)); })); return Content(data.ToString(), "text/xml"); }
返回JSON格式的數據(常用):
[HttpPost] public JsonResult JsonData() { StoryLink[] stories = GetAllStories(); return Json(stories); }
文件下載:
public FileResult AnnualReport() { string filename = @"c:\AnnualReport.pdf"; string contentType = "application/pdf"; string downloadName = "AnnualReport2011.pdf"; return File(filename, contentType, downloadName); }
觸發這個Action就會返回一個文件下載提示:
返回HTTP狀態碼:
//404找不到文件 public HttpStatusCodeResult StatusCode() { return new HttpStatusCodeResult(404, "URL cannot be serviced"); } //404找不到文件 public HttpStatusCodeResult StatusCode() { return HttpNotFound(); } //401未授權 public HttpStatusCodeResult StatusCode() { return new HttpUnauthorizedResult(); }
返回RSS訂閱內容:
public RssActionResult RSS() { StoryLink[] stories = GetAllStories(); return new RssActionResult<StoryLink>("My Stories", stories, e => { return new XElement("item", new XAttribute("title", e.Title), new XAttribute("description", e.Description), new XAttribute("link", e.Url)); }); }
觸發這個Action就會瀏覽器機會顯示: