2012-07-24 53 views
1

我不熟悉ASP.NET MVC,試圖學習基礎知識。我現在試圖學習模型,視圖和控制器之間的關係。爲什麼模型,視圖和控制器之間的交互看起來不同?

這三者之間的相互作用看起來不同,爲什麼? (看箭頭)

源1:MSDN

源2(第65頁):Steven Sanderson

,如果你幫我理清我的困惑

謝謝,我會很高興

編輯: 你在說什麼是mvc可以以不同的方式實現? (不過問asp.net的MVC - 不是一般的MVC)

我一直在尋找的mvcmusicstore ,它看起來是這樣的。 控制器:

public ActionResult Details(int id) 
    { 
     var album = storeDB.Albums.Find(id); 
     return View(album); 
    } 

型號:

public class Album 
{ 
    public int AlbumId { get; set; } 
    public int GenreId { get; set; } 
    public int ArtistId { get; set; } 
    public string Title { get; set; } 
    public decimal Price { get; set; } 
    public string AlbumArtUrl { get; set; } 

    public Genre Genre { get; set; } 
    public Artist Artist { get; set; } 
} 

觀點: (不得不添加的圖像,添加代碼以正常的方式沒有工作) The view

這看起來像MSDN版本,這將如何重寫以適合Sandersons圖? 也許這會幫助我理解!再次

編輯:

嗨再次

讓我來總結這件事。如果我錯了,請回復。 微軟希望我們使用mvc的方式就是我們在上面的MSDN鏈接和MusicStore中看到的方式。 然後還有其他「版本」的mvc,如Sandersons(或無論它來自哪裏)。 因此,微軟給我們提供了一個如何使用mvc框架的基本方法,但可以通過其他方式來完成。

一個新手不應該因爲看到不同版本而感到緊張,堅持在MSDN/MusicStore中看到的那個是完全沒問題的。

+0

根據你的編輯,我已經更新了我的答案:) – David 2012-07-25 20:40:37

回答

2

關鍵的區別在於在Sanderson圖中包含了「演示模型」。 ASP.NET MVC的實現經常使用模型作爲表示模型,即使它們可能不同(我認爲它們應該是不同的,但這是一場神聖的戰爭,沒有必要深入)。

在大多數非常簡單的ASP.NET MVC應用程序中,模型是數據實體。無論是EF實體還是Linq2Sql實體,都沒有區別。這是因爲大多數應用程序都是簡單的form-over-data,並且表示可能與持久性是一對一的。

但是,MVC模式本身不需要這個。在一個更純粹的框架無關形式中,Sanderson的圖表說明了控制器正在與模型進行交互的事實。從這個意義上說,這個模型實際上是「通往域核心的門戶」。控制器和視圖是應用程序的一部分,但是該模型具有底層業務邏輯,在其下面還有持久層和其他基礎架構信息層(當然,這些信息是分開的),這些信息對於應用程序來說是未知的。控制器和模型之間的邊界是應用程序邊界,即其他應用程序也可以連接到域核心並與之交互的點。

演示模型通常只不過是一個簡單的值對象。從某種意義上說,它不是一種實體,它不必展示任何商業行爲,也不必像持久的商業實體那樣維持其生命週期。它只是一個具有一些數據屬性的平面對象。

它可以有一些的行爲,但該行爲是爲應用程序而不是域核心。例如,也許它有一些視圖可以使用的方法或屬性。演示模型是應用程序的一部分,所以它是表示層意識。本質上它只是保存控制器需要傳遞給視圖的數據(甚至根據框架甚至從請求中接收數據)。

在ASP.NET MVC中,您經常會將該模型用作演示模型。在這些情況下,同一個對象可能扮演兩種角色,但這兩種角色是完全不同的。


編輯:只注意到你的更新問題...

在這個例子中,Album是打兩域模型和展示模型的作用。 (事實上​​,我認爲它不是一個領域模型,因爲它太貧乏了。請注意,它沒有功能,只是裸露的數據。)在更豐富的領域模型中,Album可能會有更多的功能。對於一個人爲的例子,想象一下,不是自動實現的屬性,而是它具有在設置時強制執行業務邏輯的屬性,並且它具有方法,例如AddSong(Song song)Play()以及其他這樣的行爲。

這個更豐富的模型仍然可以用作演示模型,但功能在視圖範圍內可能沒有意義。一個視圖更適合僅僅是裸露的數據元素。控制器將與模型的功能進行交互。因此,您可以在結構中創建一個類似於Album域模型的演示模型,並且它看起來就像您示例中的模型。未來,如果視圖還需要其他數據呢?也許該視圖需要了解其他模型的一些內容,這些模型不屬於與Album相同的聚合體。修改域模型以適應視圖是沒有意義的。這是倒退。演示文稿應該圍繞域核心而不是其他方式。因此,您可以將屬性添加到演示模型中,這些屬性是從控制器中的其他內容填充的。

所以,你可能最終得到這樣的事情...

領域模型:

public class Album 
{ 
    public int ID { get; private set; } // might need to be immutable 

    private string _title; 
    public string Title 
    { 
     get { return _title; } 
     set 
     { 
      // don't allow empty titles 
      if (string.IsNullOrWhiteSpace(value)) 
       throw new ArgumentNullException("Title"); 
      _title = value; 
     } 
    } 

    private Album() { } 
    public Album(int id, string title) 
    { 
     ID = id; 
     Title = title; 
    } 

    public void Play() 
    { 
     // some implementation 
    } 

    public void SomeOtherMethod() 
    { 
     // some implementation 
    } 
} 

隨着業務領域的發展和變化,這種模式可能會隨之改變。主要的一點是它根據域名核心和業務邏輯的要求而改變,而不是根據UI實現的要求。

使用該域核心的特定網站上的特定「頁面」可能需要關於專輯的特定信息,並且可能還需要其他一些信息。你會定製的演示模型,以適應這些,那麼

public class AlbumViewModel 
{ 
    public int ID { get; set; } 
    public string Title { get; set; } 
    public string Owner { get; set; } 
    public IEnumerable<Listener> Listeners { get; set; } 
    public string SomeCompletelyUnrelatedValueNeededByTheView { get; set; } 
} 

控制器將構建此演示模型視圖:

public ActionResult Details(int id) 
{ 
    // TODO: validate and sanitize any inputs 

    var album = AlbumRepository.Get(id); // after all, why bind the UI _directly_ to the DB? that's just silly 
    var someOtherObject = SomeOtherRepository.Get(someOtherValueFromSomewhereElse); 

    var albumVM = new AlbumViewModel 
    { 
     ID = album.ID, 
     Title = album.Title, 
     Owner = somethingElse.SomeValue, 
     Listeners = someOtherObject.GetListeners(album), 
     SomeCompletelyUnrelatedValueNeededByTheView = "foo" 
    }; 

    return View(albumVM); 
} 

這是整個一個更手動方法。當您有更復雜的領域模型,與該領域交互的多個複雜應用程序,遍及整個領域的不同技術堆棧等等時,這非常有用。對於簡單的數據形式應用程序,標準的ASP.NET MVC實現通常工作正常。大多數教程都反映了這一點,將多個職責合併爲更少的對象,使用裝飾器代替顯式代碼(假設使用相同的工具堆棧)等。

您正在查看的示例使用非常少的代碼就可以快速獲得一個可用的應用程序。就像任何框架一樣,如果你按照框架的意願去做,那麼它就可以很好地工作。如果您需要需要以超出框架的範圍,您仍然可以以更抽象且與框架無關的方式維護該模式。


編輯:再次您的更新...

從某種意義上說,是的。 ASP.NET MVC是一個借鑑MVC模式的框架。與所有事情一樣,有不止一種方法可以做到這一點。堅持簡單的實現和快速的應用程序,由ASP.NET MVC框架提供的功能,並在其各種教程中解釋是完全可以接受的,並且是使用框架的一個很好的例子...使用工具完成工作。

他們堅持所有最有意義的方式。然而,與此同時,在框架的真實性質中(它通常超出了模式描述的範圍),它們試圖給你一些工具,使得實際開發工作變得非常輕鬆。如果您沒有迫切需要將您的域模型與演示文稿模型分開,則不需要。一個模型可以扮演兩種角色。如果您沒有迫切需要將數據訪問抽象化,比如存儲庫模式,那麼您不必這樣做。您可以將一些快速的實體框架功能直接放在您的模型中,並完成它。

最終它取決於項目的需求,開發人員的喜好等等。模式更具學術性,框架更實用。平衡兩者是關鍵。

+0

嗨,大衛。我做了一個小小的更新。請看一看。 – 2012-07-26 20:30:31

+0

@CliffSmith:已更新。這可能是我最長的堆棧溢出答案:) – David 2012-07-26 21:01:10

+0

我很高興聽到您已創建新記錄=) 非常感謝您的承諾。 (對其他人也是如此) 我想我現在可以控制我的困惑。 祝您有愉快的一天 – 2012-07-27 19:56:34

1

我想區別是,在asp.net MVC中,您可以強有力地鍵入視圖,這些視圖具有模型的「知識」和實體被傳遞給視圖。儘管視圖不應該(或者更確切地說,不需要)對模型有任何瞭解,但它最純粹的意義。出於這個原因,我說史蒂文桑德森的例子是更好的。

他的方式神奇的書!

0

我不會出汗 - 斯蒂芬桑德森的圖表顯示的週期較少,但更詳細。

我解釋MS物品如箭頭:

  • 控制器填充模型(來自服務等)
  • 控制器指示,以查看
  • 查看填充通過結合模型

儘管在我看來,微軟圖表並沒有真正有用或者信息豐富或者有用。你也可以同樣認爲箭頭可以朝不同的方向發展 - 甚至可以像桑德森那樣在兩個方向發展。例如。控制器也收到綁定等模型

桑德森箭頭註釋得很好,是自我明確的,這本書是偉大的。

相關問題