[自我修練] 第一次實作MVC的重點筆記

  • 20603
  • 0

看書看了半天,還是要動手實作並做筆記才能真正吸收,廢話不多說,紀錄一下我自己的重點...

看書看了半天,還是要動手實作並做筆記才能真正吸收,廢話不多說,紀錄一下我自己的重點:

當Server接受到Request的時候,就依照Global.asax.cs裡面所定義的MapRoute決定由哪個Controller來進行什麼樣的Action
所以Global.asax.cs會長得像這樣:


public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            //定義不要透過Routing處理的網址
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", //定義網址路由的名稱
                "{controller}/{action}/{id}", //定義解析網址的格式
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
              // 定義上面解析網址的預設值,解析不出來的網址自然就是回給使用者404 Not Found的頁面
            );
        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterRoutes(RouteTable.Routes);
        }
    }

執行ASP.NET MVC時,會傳遞Controller和action變數給System.Web.Mvc.MvcHandler類別,然後再傳給DefaultControllerFactory建立Controller執行個體

Controller類別的條件:
1.檔名一定要有Controller結尾
2.繼承於Controller基底類別(或實作IController介面的類別
3.類別中包含數個回傳值為ActionResult的公開方法


在Controller資料夾按右鍵新增一個Controller之後,Controller會長得像這樣:


public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }

其中View是來自於Controller基底類別的一個輔助方法,會回傳繼承ActionResult類別的ViewResult物件
由前面的MapRoute定義可以知道當使用者提出了/Home/Index或/Home的要求,都會執行到上面HomeController類別的Index方法

接著在Index方法的任何一個地方,可以透過按滑鼠右鍵出現的選單加入"檢視頁面",像下面這樣:


其中的建立強型別檢視就代表著可以在檢視頁面上使用所選擇的型別來顯示資料
簡單來說,這是一個可以少打很多字、快速建立檢視頁面的功能
但是要注意的是"在沒有建置過"或是"型別有修改過",都應該要先建置過再執行"加入檢視"的動作,這樣產生的檢視才會正確

沒有選擇強型別所建立的檢視,可視情況在action方法用ViewData或TempData顯示資料,但通常透過Model或ViewModel來顯示資料會比較恰當

在Models資料夾可透過新增ADO.NET Entity Data Model的方式,從資料庫建立所需要的Model;而自定的ViewModel,同樣加在Models資料夾底下,統一管理

透過資料模型繫結(Model Binder)的機制會自動把QueryString或Form傳來的資料變成Controller中Action方法的參數,像這樣:


public ActionResult Save(string Name, string Content)

如果直接修改Action方法的參數型態,也會自動把傳來的資料轉型成該參數型態,但也要注意傳來的資料是否為正確的型態
當然,也可以透過自定ViewModel的方式收取使用者輸入的資料,ViewModel會像這樣:


public class GuestBookWrite
    {
        [Required] //表示這欄位的資料為必填
        public string UserName { get; set; }

        [DataType(DataType.EmailAddress)] //指定DataType為EmailAddress並以正規表示法設定資料驗證規則
        [RegularExpression(@"^[a-z0-9\._%+-]+@[a-z0-9\.-]+\.([a-z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum)$")]
        public string Email { get; set; }

        [Required]
        public string Contents { get; set; }
    }

檢視畫面會像這樣:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.GuestBookWrite>" %>
Inherits就是自訂的ViewModel
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
 Write
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm("save", RouteData.Values["controller"].ToString(), FormMethod.Post)) { %>

    <%= Html.ValidationSummary() %>

    <%= Html.LabelFor(x => x.UserName) %>
    <%= Html.TextBoxFor(x => x.UserName)%>
    <%= Html.ValidationMessageFor(x => x.UserName) %>
    <br />

    <%= Html.LabelFor(x => x.Email) %>
    <%= Html.TextBoxFor(x => x.Email)%>
    <%= Html.ValidationMessageFor(x => x.Email) %>
    <br />

    <%= Html.LabelFor(x => x.Contents) %>
    <%= Html.TextAreaFor(x => x.Contents) %>
    <%= Html.ValidationMessageFor(x => x.Contents) %>
    <br />
    <input type="submit" />
<% } %>
</asp:Content>

其中綠色字體的部份是用在Client端執行javascript的驗證
需先在Site.Master的<head>標籤區段中引用下面三個js檔:
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcValidation.js" type="text/javascript">

使用<% Html.EnableClientValidation(); %>要注意的是:
1.如果在一個頁面中有兩個以上的表單要驗證,則必須出現在第一個Html.BeginForm宣告之前,否則會無法執行
2.一定要用Html.BeginForm宣告表單,用自行撰寫的<form>標籤將會無法正常使用


接下來在表單裡面使用<%= Html.ValidationSummary() %>顯示所有驗證失敗的結果
並在每個欄位旁邊加上
Html.ValidationMessageFor,顯示驗證失敗的錯誤提示

紫色字體的<% using (Html.BeginForm("save", RouteData.Values["controller"].ToString(), FormMethod.Post)) { %>
是表單的寫法,路由值(RouteValue,即RouteData.Values["controller"])的名稱在MVC2中只有controller、action和area是內建的,
而area只有在連結到Area區域網站時才有值,其它路由值的名稱都可自訂
自訂的路由值都會在Global.asax.cs檔案的RegisterRoute方法中定義


以下是一個可以儲存GuestBookWrite的自訂ViewModel資料到資料庫的action方法範例:


[HttpPost] //表示這個action方法只接受HTTP POST傳來的資料
             //專有名詞叫"動作過濾器"(Action Filter)或"動作選擇器"(Action Selector)
public ActionResult Save(Models.GuestBookWrite data) //傳來的資料已自動轉成GuestBookWrite型別
{
 //以自訂ViewModel裡所定義的規則驗證輸入的資料是否正確
 if (!ModelState.IsValid)
 {
   return RedirectToAction("Write");
 }

 MvcApplication1.Models.MVC2Entities db
 = new Models.MVC2Entities();

 db.AddToMessage(new Models.Message()
 {
   ID = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"),
   UserName = data.UserName,
   Email = data.Email,
   Contents = data.Contents,
   CreateTime = DateTime.Now
 });

 db.SaveChanges();
            
 //再把資料傳回畫面上顯示
 return View(data);
}

 建立Model、Controller、View,大致上先紀錄到這裡...