2009-04-17 18 views
4

條件從的NerdDinner ASP.NET MVC範例應用程序MVC - 在視圖

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> 
<% 
    if (Request.IsAuthenticated) { 
%> 
     Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>! 
     [ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ] 
<% 
    } 
    else { 
%> 
     [ <%= Html.ActionLink("Log On", "LogOn", "Account") %> ] 
<% 
    } 
%> 

這是命名爲LoginStatus.ascx局部視圖用戶控件引用。正如你所看到的那樣,存在改變視圖的「整個」輸出的條件。這是正確的方法。如果控制器評估這種情況,然後渲染適當的局部視圖,會不會更好?

不管你對上一個問題的回答如何在ASP.NET MVC中採用後一種方法,即父視圖可以調用控制器(而不是執行UserControl的RenderPartial),並讓它決定哪個部分視圖呈現?

+0

@Ngu Soon Hui:謝謝 – 2009-04-17 07:51:51

回答

4

如何對這種做法:

解決方案1 ​​

創建於HtmlHelper擴展方法,這將使得無論是 「WelcomeMessage.Anonymous.aspx」 或 「WelcomeMessage.Authenticated.aspx」 視圖基於請求。下/瀏覽/分享

/Views/Shared/LoginStatus.Anonymous.ascx 
/Views/Shared/LoginStatus.Authenticated.ascx 

解決方案2

<%= Html.LoginStatus() => 

並把這些意見:

只需更換if/else陳述與ASP.NET的LoginView控制在LoginStatus.ascx

<asp:LoginView Runat="Server"> 
    <LoggiedInTemplate> 
     Welcome, <%= Html.Encode(Model.UserName) %>! 
     <button>Sign Out</button> 
    </LoggedInTemplate> 
    <AnonymousTemplate> 
     <button>Sign In</button> | <button>Join Now!</button> 
    </AnonymousTemplate> 
</asp:LoginView> 

參見:

+0

@Koistya Navin .NET:很好的黑客,但問題依然存在。我能不採取我用ASP.NET MVC描述的第二種方法嗎? – 2009-04-17 08:11:17

1

我認爲如果視圖會因此而改變,那麼視圖的責任就是強制執行此操作。但是如果條件改變而不是外觀(即「負數應該是紅色的」)而是行爲(即「如果用戶登錄他/他必須看到註銷按鈕而不是登錄按鈕」),那麼它是控制器的決定。您可能會在控制器和頁面之間引入「渲染器」級別。

+0

我傾向於贊同你的推理,但不是你的榜樣。按鈕是視圖的責任。那麼你還會讓控制器決定是否打印/不打印要顯示的視圖?我會讓一個CSS文件做到這一點。 – 2009-04-17 08:06:52

+0

由於該按鈕允許用戶執行某些操作(例如,登錄),如果她已經記錄了,您可能不希望她執行任何操作,您仍然必須編寫邏輯來阻止她調用URL「http:// mysite .org/login?username = mickey&password = goofy「(只是一個例子... :) - 所以這與」print/dontprint「不同,根據您使用的媒體,這可能很容易決定。 – 2009-04-17 08:52:46

0

我覺得你在做什麼是非常好吧。諸如展示變化之類的小事情可以並且應該由觀點來進行。

例如,我有一個由單獨的ascx呈現的主菜單。裏面有很多這樣的小檢查來決定要顯示哪些文本以及哪些樣式適用於列表元素。

如果有很大的決定像基於某些用戶操作考慮渲染哪個視圖那麼控制器會詢問業務邏輯並決定返回哪個視圖以重定向到哪裏。但是,如果它是一個相當穩定的UI元素,只有文本和顏色選項稍有改變,那麼就把必要的邏輯加入其中。

您還可以將一個單獨的模型傳遞給您的ascx,並使用幾個標誌來定義顯示內容和顯示方式。然後,設置這些標誌的實際邏輯將位於業務邏輯層的其他位置,並且您的所有視圖都會查看這些標誌並進行相應的渲染。

別擔心,你做得對。

0

相反,如果用戶在查看認證決定的,你能做到在控制器中,像這樣:

public ActionResult ShowAPage() 
{ 
    if(!HttpContext.User.Identity.IsAuthenticated) 
    { 
     return RedirectToRoute("ShowLoginPage") 
    } 
    return View(); 
} 

然後你就可以重定向到登錄頁面,而不是在一個視圖中有這樣的邏輯,這不是真正的問題分離。

這樣做的一個非常酷的方式是爲認證用戶使用不同的母版頁,而不是未經認證的用戶。我認爲你要始終顯示登錄或註銷鏈接,這樣你可以使用ActionFilter根據用戶的認證來更改主頁面。然後,您登錄的用戶可以獲得像導航欄那樣的內容,您可能想要從外部隱藏,而無需在顯示邏輯中進行確定。

這裏有一種不使用動作過濾器的方法,但可以採用各種方法,一個好的方法是創建一個自定義控制器,該控制器從控制器繼承並覆蓋View方法以選擇適當的母版頁。

public ActionResult ShowAPage() 
{ 
    if(!HttpContext.User.Identity.IsAuthenticated) 
    { 
     return View("ShowAPageView", "LoggedInMasterPageName"); 
    } 
    return View("ShowAPageView", "LoggedOutMasterPageName");  
} 

希望這會有所幫助。