2010-10-25 28 views
1

經過這麼多年使用ASP.Net,我仍然試圖找出如何使用MVC實現相同的結果。MVC - 多個強類型的對象...在一個視圖

我有一個控件強類型的東西的materpage。當我導航到不同的強類型模型的視圖...並單擊按鈕執行某些操作時,我得到「傳入字典的模型項目類型爲Site.Models.RegisterModel」,但此字典需要模型「Site.Models.LogOnModel」類型的項目。

爲了這個例子,我們可以使用VS 2010提供的Default MVC應用程序,讓我們想象一下我想更改「LogonUserControl.ascx」,以便它告訴我登錄的用戶(因爲它工作目前)或允許我從那裏登錄,向我顯示用戶名和密碼的文本框(因此在這種情況下從主頁)。

所以我採取了控制和強烈鍵入如下:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Gioby.Models.LogOnModel>" %> 
<% 
    if (Request.IsAuthenticated) { 
%> 
     Welcome <b><%: Page.User.Identity.Name %></b> 
     [ <%: Html.ActionLink("Log Off", "LogOff", "Account")%> ] 
<% 
    } 
    else { 
%> 
    <% using (Html.BeginForm()) { %> 
     <div id="logon"> 
       <div class="editor-label"> 
        <%: Html.LabelFor(m => m.UserName)%> 
        <%: Html.TextBoxFor(m => m.UserName)%> 
        <%: Html.ValidationMessageFor(m => m.UserName, "*") %> 
        <%: Html.LabelFor(m => m.Password)%> 
        <%: Html.PasswordFor(m => m.Password)%> 
        <%: Html.ValidationMessageFor(m => m.Password, "*") %> 
        <input type="submit" value="Log On" /> 
       </div> 

       <div class="editor-label"> 
        <%: Html.ActionLink("Register here", "Register", "Account")%> 
        <%: Html.CheckBoxFor(m => m.RememberMe, new { @class = "pad-left" })%> 
        <%: Html.LabelFor(m => m.RememberMe) %> 
       </div> 
     </div> 
    <% } %> 
<% 
    } 
%> 

然後在HomeController中,我添加了一個程序爲:

[HttpPost] 
public ActionResult Index(LogOnModel model, string returnUrl) 
{ 
    if (ModelState.IsValid) 
    { 
      // ==>> Check Login against your DB 

      // Now check if param returnUrl is empty 
      if (!String.IsNullOrEmpty(returnUrl)) 
       return Redirect(returnUrl); 

      return RedirectToAction("Index", "Home"); 
    } 

    // If we got this far, something failed, redisplay form 
    return View(model); 
} 

我在主頁上測試它...它的工作原理!

但是,當我瀏覽到「註冊」視圖(請記住,「LogonUserControl.ascx」位於裏面的「母版」,因此從註冊視圖中可見)。

所以,當我點擊註冊按鈕,我得到的錯誤: 傳遞到字典的模型產品類型Site.Models.RegisterModel的」,但這部詞典需要類型Site.Models.LogOnModel的模型項目」。

問: 是否意味着我將永遠無法在不同拼湊成一個看法?

比方說,我想寫一個電子商務網站,並在主頁上我想看到「最常用的標籤」,「大多數購買的產品」,「本月產品」,「類別列表」......所有相同的視圖,每個人都有自己的HTTP POST操作。

如果這可以使用MVC?

+1

您的'Register'控制器操作在哪裏?你從上面的例子中忽略了它嗎? – 2010-10-25 19:37:05

回答

0

如果我理解正確的問題,你必須使用相同的母版,但針對不同的ViewModels是強類型的兩個視圖。母版頁可以包含也是強類型的部分視圖,只要其預期的ViewModel與父視圖相同即可。但是,如果您使用不同ViewModel類型的視圖,它不知道該怎麼做。

考慮以下幾點:

<% Html.RenderPartial("LogOn") %> 

上面的代碼隱式包括用於當前視圖中的模型數據被呈現。這和你說過的完全一樣:

<% Html.RenderPartial("LogOn", Model) %> 

所以這隻會在Model是LogOnModel時才起作用。請記住,MasterPage實際上是View繼承它的一部分,所以即使你把它放在MasterPage中,就好像你將相同的代碼放在每個繼承它的視圖中。因此,如果您的視圖模型與PartialView的模型不同,這將無法使用。另一種方法是使用繼承來確保每個ViewModel都將包含Master Page所需的所有信息。這種方法詳細描述在here

但是這種方法意味着您必須始終使用工廠來生成您的視圖模型,並且每個視圖模型必須知道它將使用哪個主頁面。在我們的產品中,我們可以在同一視圖中使用不同的主頁面,具體取決於用戶在何種模式下查看網站,因此將ViewModel與主頁面的模式綁定是沒有意義的。我們使用RenderAction方法完成您所描述的內容,該方法允許您呈現整個控制器操作,就好像它只是大視圖的一部分。這種方法的一些優點在here討論。

所以,現在你可以有你的母版包括任何你想要的小部分觀點,但你建立這些意見的視圖模型到一個單獨的控制器的行動,負責該特定部分景觀獨立的邏輯:

<% Html.RenderAction("LogOnBox") %> 

行動:

public ActionResult LogOnBox() 
{ 
    LogOnModel model = GetLogOnModel(); 
    return PartialView("LogOnUserControl", model); 
} 

現在,不管什麼型號的當前視圖使用,您的主頁面可以包括「本月產品」,「最常用的標籤」,「大多數買產品」,「列表類別「等更好的是,頁面的這些部分可以利用輸出緩存,因此如果它們不經常更改,則不必在每次加載頁面時都進行重新生成。

+0

不知道如何RenderAction會工作...你是否說使用它,而不是RenderPartial? RenderAction不是對方法的調用嗎? – 2010-10-26 08:00:33

+0

@Filu:查看我更新的答案。 – StriplingWarrior 2010-10-26 15:48:28

+0

爲了澄清,我們是否說每當我們創建一個局部視圖(即一個Control.ascx),爲了它的工作,它需要有他自己的ControllerFile.cs和自己的ModelFile.cs? 然後,如果我們使用RenderAction,則在View或MasterPage上我們要使用局部視圖...應該有效。 如此理想的情況下,我們可以擁有一個包含10個局部視圖的視圖,每個視圖都將指向他們自己的控制器和自己的模型,即使主視圖屬於另一個模型/控制器也是如此? 我仍然需要研究如何使用MVC與緩存,但肯定是在要做的事情列表。 – 2010-10-27 20:35:32

相關問題