DCSIMG
ASP.NET MVC Preview 3: How to create simple MVC application - Tamir Shlomi's Blog

Tamir Shlomi's Blog

Welcome to Tamir Shlomi's blog. All about .NET, OOP and SQL server

ASP.NET MVC Preview 3: How to create simple MVC application

 

היי כולם.
בפוסט הזה נסביר איך ליצור דפי web בארכיטקטורת ASP.NET MVC (גירסת ה CTP 3).

הקדמה ל ASP.NET MVC :
ארכיטקטורת ה ASP.NET MVC מבצעת חלוקה באפליקציות ווביות בין ה UI לבין ה Data
שאמור להיות מוצג בדפי אינטרנט, ע"י מידול ה Web Application שלנו לשלוש שכבות:
Model, View And Controller.
ה View אמור להציג את הנתונים בלבד. View לא מכיר שום מקור נתונים ולא מבצע שום
מניפולציה על Data. תצוגה נטו. View אמור להיות "טיפש" ככל שניתן.
ה Model מנהל את ה business logic של האפליקצייה ואת הגישה למקור הנתונים.
ה Controller מגשר בין ה Model וה View ודואג לבצע את השליפות בעזרת ה Model
ואת שתילת הנתונים שהתקבלו לאחר ביצוע הפעולות הדרושות, אל תוך ה View.

דבר ראשון, ניצור אפליקציית ASP.NET MVC חדשה:

NewMvcApp

[ניתן לוותר על יצירת Test Project בדוגמא זו]

בברירת המחדל, קיבלנו template המכיל כבר Controller ו View מוכנים.

יצירת ה Controller:
בספריית ה controllers נוסיף item חדש מסוג "MVC Controller Class" , ונקרא לו בשם DataController.
[חובה לציין את הסיומת "controller" בסוף השם].

NewController

ב controller החדש שיצרנו נקבל Action שנקרא "Index", שמחזיר ActionResult.
ע"מ שלא נחטוף Exception כשנכנס ל action הזה, נממש אותו בצורה הבאה:

public ActionResult Index()

{

     ViewData["Title"] = "Data Controller Page";

     ViewData["Message"] = "Welcome to ASP.NET MVC!";

 

     return View();

}

 

בנוסף, יש להעתיק את הקובץ Index.aspx ואת קובץ ה code-behind שלו מהספרייה "Home" אל הספרייה "Data" ע"מ שיהיה View שה action יוכל להתרנדר אליו.

בגלל ההבדלים במיקום הקובץ יש לשנות ב Page Directive את ה Inherits ב Markup, ואת הגדרת

ה namespace ב code-behind במקום MyMvcWebSite.Views.Home לערך החדש MyMvcWebSite.Views.Data

 

עכשיו ניצור שני actions חדשים משלנו, ונקרא להם ProductInfo, ו CategoryInfo:

 

public ActionResult ProductInfo(int? id)

{

   if (id.HasValue)

   {

        // Get the Product object from the Model layer

        NorthwindDataService service = new NorthwindDataService();

        Product product = service.GetProduct(id.Value);

 

        ViewData["ProductName"] = product.ProductName;

        ViewData["categoryID"] = product.CategoryID;

   }

 

   return View();

}

 

public ActionResult CategoryInfo(int? id)

{

   if (id.HasValue)

   {

        // Get the Category object from the Model layer

        NorthwindDataService service = new NorthwindDataService();

        Category category = service.GetCategory(id.Value);

  

        ViewData["categoryName"] = category.CategoryName;

        ViewData["categoryDesc"] = category.Description;

   }

 

     return View();

}

 

בכדי לשלוף את הנתונים אנו עושים שימוש במחלקה NorthwindDataService שנמצאת ב Model Layer.

ספריית ה Models לא ניגשת בשום צורה ל Views או מטפלת בקריאות מתוך ה Views באופן ישיר.

ברמת העיקרון, ספריית ה Models מטפלת ב business logic של האפליקצייה שלנו, מכילה את הגדרת הישויות שיצרנו ומנהלת את התקשרות בין האפליקצייה למקור הנתונים.

לכן ב action methods אנו ניגשים למחלקה NorthwindDataService והיא זו שניגשת ל DB ושולפת עבורנו את ה Data הרצוי.

 

הסבר על פעולות ה action methods:

כשאנו עובדים ב ASP.NET MVC וגולשים ל URL מסויים, מנוע ה Routing (עליו נרחיב בהמשך) הופך את הכתובת שנמצאת ב address bar להפנייה ל Controller/action/parameter לפי מה שמוגדר by default. מנוע ה routing יודע להפנות אותנו ל controller המבוקש, ובתוכו ל action method שאמורה לטפל ב request הנוכחי. במידה ויש פרמטר הוא מתקבל ב parameter list של ה method.

בכדי שלא נקבל שגיאה במידה ולא התקבל פרמטר משורת הכתובת, אז הפרמטר צריך להיות reference type או nullable value type. אחרת, במידה והעברת הפרמטר כשלה, תתקבל שגיאה במע'.

אחרי שליפת הנתונים וקבלת ה entity המתאים, אנו מאתחלים dictionary מסוג ViewDataDictionary שמכיל את האובייקטים שיועברו ל UI בהמשך ומאוסנים לפי אינדקס כרגיל ב Dictionary.

בקריאה ל ()return View ה ViewData עובר ל View המתאים.

 

 

יצירת ה View:

אחרי שיצרנו את ה action של ה controller ניצור את ה View שיציג את ה rendered html שה controller מייצר לנו ע"י ה action בו השתמשנו.

נתחיל בהוספת תקייה חדשה לתקיית ה Views.

שם התקייה חייב להיות זהה לשם ה controller אותו אנו מעוניינים להציג, אך ללא הסיומת "controller". לכן, אם ה controller שלנו היה "DataController", שם התת-הספרייה יהיה "Data".

לתקייה נוסיף שני  items חדשים מסוג MVC View Content Page (ע"מ שיירש את ה MasterPage שנמצא בתקייה Views=>Shared) ונקרא להם בשמות התואמים ל action methods שלהם.

לכל action method יש את ה view משלו.

[ניתן להשתמש ב view יחיד לכמה actions אך לצורך הדוגמא ניצור לכל action method את ה view שלו]

 

CraeteNewViewContentPage

 

ה items שנוספו (MVC View Content Pages) יורשים מהמחלקה ViewPage שיורשת מ Page ומממשת את IViewDataContainer.

ירושה מ IViewDataContainer חושף לנו את ה ViewData property שמנגיש לנו את הערכים שהזנו ב controller.

 

עכשיו מבנה ה Solution שלנו נראה כך:

 

solutionTreeView

 

בשונה מ WebForms אין צורך להגדיר דבר ב code-behind של דפי ה aspx. הדבר היחיד שחשוב לנו שם הוא ההגדרה שהמחלקה שלנו יורשת מ ViewPage.

 

public partial class ProductInfo : ViewPage

{

}

 

ה Page Directive של CategoryInfo / ProductInfo יראה כך:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="ProductInfo.aspx.cs" Inherits="MyMvcWebSite.Views.Data.ProductInfo" %>

מבנה הגדרת ה Inherit ב Page Directive בנוי כ Application.Views.Controller.View
ולכן הערך שלו יהיה MyMvcWebSite.Views.Data.ProductInfo.

ה Markup שלנו עושה שימוש ב Helpers ע"מ לייצר את ה HTML.
בכדי לשלוף את המידע ששתלנו ב Controller ולהפוך אותו ל HTML נבצע את הפעולות הבאות:

[ProductInfo.aspx Markup]

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h2>Product Name:
     <%= Html.Encode(ViewData["ProductName"]) %></h2>
     <%= Html.ActionLink("Link to category",
                         "CategoryInfo",
                          new RouteValueDictionary{
                          {"id", ViewData["categoryID"]}}
                         )%>
</asp:Content>

[CategoryInfo.aspx Markup]

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h2>Category Information</h2>
<p><b>Category Name:</b>
<%= Html.Encode(ViewData["categoryName"])%></p>
<p><b>Category Description:</b>
<%= Html.Encode(ViewData["categoryDesc"])%></p>
</asp:Content>

About Helpers:

ישנם כמה "Helpers" שעוזרים לנו לייצר את ה UI ולגשת לערכים הקיימים ב ViewData (אותם
שתלנו ב controller).
יש את המתודה (Html.Encode(object value שמייצרת לנו את ה HTML מתוך האובייקט
אותו אנו מספקים כפרמטר.
לדוגמא, בעמוד ProductInfo אנו ניגשים לערך שנמצא ב ViewData Dictionary
באינדקס "ProductName". הערך שנקבל יהיה string שאותחל ב Controller. אותו נהפוך ל HTML
ע"י שימוש ב ()Html.Encode וע"י כך אנו יוצרים את התוכן של תגית <h2>.
בהמשך אנו יוצרים ActionLink, שוב ע"י ה Html Helper. אנו מספקים את ה like text כפרמטר ראשון,
את ה "action" אליו אנו פונים, ולאחמ"כ את ה values אותם אנו רוצים להעביר ל action method אליו
אנו פונים ע"י ה link. ה Target URL מיוצר אוטומטית ע"י מנגנון ה routing של ASP.NET MVC
לפי הכללים שהגדרנו בהרשמת ה Routes ל route collection של האפליקצייה שלנו.
CategoryInfo.aspx עושה שימוש דומה למדי ב Html Helpers כמו ProductInfo.aspx.
זהו.
יש לנו עכשיו אפליקציית MVC מוכנה.
נריץ, ונגיע לעמוד Home.
נשנה את ה URL ל 1/http://server/Data/ProductInfo

מה שיקרה עכשיו, זה שה Data Controller ייקרא לפעולה, יבצע Invoke ל action method

המתאים => ProductInfo ויעביר את הפרמטר "1".
נקבל את העמוד שמכריז על שם המוצר, ואת הלינק שמוביל לקטגוריה אליה הוא שייך.

לחיצה על הלינק פותחת את העמוד Category Information עם שם הקטגורייה ותיאורה.
בהצלחה,
תמיר.

Comments

Guy Burstein said:

welcome!

# July 8, 2008 8:40 PM

Eyal Zoref said:

Great Introduction!

What about unit testing of Views?

# January 18, 2009 4:41 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: