1. 程式人生 > >ASP.NET MVC 入門5、View與ViewData

ASP.NET MVC 入門5、View與ViewData

本系列文章基於ASP.NET MVC Preview5.

view在MVC模式中與使用者進行最直接的接觸,它負責資料的呈現。這裡要注意一點就是,view只是負責資料的呈現,所以我們應該要儘量讓view中不涉及業務邏輯的處理。

我們來新增一個Blog首頁的view。在安裝了ASP.NET MVC後,我們在新增新專案的時候可以看到有MVC的view模板:

image 
注:如果你的是中文版的VS,安裝完後可能會出現找不到這個模板的現象,你可以參考在中文版VS 08中安裝MVC這篇文章設定一下。

其中MVC View Content Page是有母版頁的。我們在Views/Home目錄下新增一個MVC View Content Page,並選擇我們Views/Shared目錄下的Site.Master母版頁:

publicpartialclass Index : ViewPage
{
}

ASP.NET MVC預設是使用WebForm來作為view的。所以我們看到新建的aspx頁面繼承自ViewPage,如果使用aspx頁面作為ASP.NET MVC的檢視引擎,則所有的aspx頁面都必須繼承自ViewPage。我們再看一下ViewPage:

image

我們看到ViewPage繼承自ASP.NET WebForm的Page頁,還實現了IViewDataContainer介面,同時還提供了一些Helper類的例項。我們可以使用ViewData來從Controller中往view頁面中傳遞資料。下面我們在HomeController中的Index Action中取出Posts列表,然後在View中顯示。我們先在Controller中取出資料,前面說過,為了方便,我們會直接使用BlogEngine的Model層來作為我們這個4mvcBlog的Model。所以我們的程式碼如下:

public ActionResult Index(int? id)
{
    ViewData[
"Title"] = BlogSettings.Instance.Name;

    List
<IPublishable> posts = BlogEngine.Core.Post.Posts
        .ConvertAll(
new Converter<Post, IPublishable>(delegate(Post p) { return p as IPublishable; }));

   
int pageIndex = (id
!=null&& id.HasValue && id.Value >0) ? id.Value : 1;
   
int pageSize = Math.Min(posts.Count, BlogSettings.Instance.PostsPerPage);
   
if ((pageIndex -1) * pageSize + pageSize > posts.Count)
    {
       
return ShowMsg(new List<string>() { "頁碼超出範圍" });
    }
    posts
= posts.GetRange((pageIndex -1) * pageSize, pageSize);

    ViewData[
"Posts"] = posts; //向ViewData中傳資料

   
//這裡返回View給客戶端,如果不指定要返回的View的名稱,
   
//就是返回和Action同名的View,
   
//也就是相當於return View("Index");return View();
}

預設的WebFormView搜尋View的順序是按如下順序搜尋的:

image

其中{1}為ControllerName,{0}為ActionName。MasterLocationFormats為母版頁的搜尋順序。

在上面的程式碼中我們使用ViewData["Posts"]向View頁面傳遞資料,然後我們就可以在View中取出資料並呈現給使用者,Views/Home/Index.aspx頁面的部分程式碼如下:

image

如上紅色框中的程式碼,我們可以從ViewData中取出資料,並轉換為相應的型別。在這裡我們發現ViewData要做一個型別的轉換,其實我們可以將ViewData.Model設定為強型別,只需將我們的View頁面繼承自ViewPage<TModel>就可以了:

image

然後在Controller裡面return View()的時候直接給ViewData.Model傳值,如下所示:

image

然後在View中我們可以直接從強型別的ViewData.Model中取值:

image

由上面的程式碼我看可以看出ViewData.Model就是List<IPublishable>型別,並不需要再進行型別的轉換。

ViewData還有一個Eval的方法,我們可以使用這個方法從ViewData中取值。假如我麼在Action中使用return View(Post);給View傳遞一篇日誌的資料。而Post有一個Previous的屬性指向前一篇日誌,則我們可以在View頁面中可以這樣來取值:

<%= ViewData.Eval("Previous.Title")%>

但是如果使用我最後提供的示例Blog程式的程式碼這樣在取值的時候直接在裡面使用"."來取值,你會發現取不了值。因為BlogEngine裡面的BusinessBase類實現了IDataErrorInfo介面,而IDataErrorInfo有一個索引器,也就是說BusinessBase有一個索引器,就因為有一個索引器,使Eval中不能用點來取值(不知道是不是bug?)。

補充:上面說到的不是Bug,是因為BusinessBase實現了IDataErrorInfo介面,該介面有個索引器,導致ViewData.Eval()方法呼叫時搜尋索引器的值時返回String.Empty而使ViewData.Eval()認為是找到值了,從而失效。

image

我們可以將return string.Empty修改為return null,這樣就可以了。

好,這一部分就先到這裡吧。Enjoy!Post by Q.Lee.lulu

---------------------------------------------------------------------