2011-05-03 39 views
15

我有使用Razor引擎的MVC 3 C#項目。有什麼方法,我猜,將動態數據寫入_Layout.cshtml的最佳實踐是什麼?如何在MVC 3 Razor中將動態數據寫入頁面佈局?

例如,也許我想在我的網站的右上角顯示用戶的名字,這個名字就是從會議,DB,或任何基於中記錄哪些用戶的到來。

謝謝您。

更新:我還在尋找將某些數據呈現到佈局元素的良好做法。例如,如果我需要根據登錄用戶的憑據來呈現特定的CSS文件。

(對於上面的例子,我想使用URL傭工)

回答

19

Visual Studio創建默認的Internet應用程序中使用_LogOnPartial.cshtml做的正是這一點。

用戶名值在HomeController的

代碼的登錄操作設置_LogOnPartial.cshtml

@if(Request.IsAuthenticated) { 
    <text>Welcome <strong>@User.Identity.Name</strong>! 
    [ @Html.ActionLink("Log Off", "LogOff", "Account") ]</text> 
} 
else { 
    @:[ @Html.ActionLink("Log On", "LogOn", "Account") ] 
} 

User.Identity是ASPNET會員提供商。

代碼爲_Layout.cshtml

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <title>@ViewBag.Title</title> 
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> 
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> 
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script> 
</head> 
<body> 
    <div class="page"> 
     <header> 
      <div id="title"> 
       <h1>Test</h1> 
      </div> 
      <div id="logindisplay"> 
       @Html.Partial("_LogOnPartial") 
      </div> 
      <nav> 
       <ul id="menu"> 
       </ul> 
      </nav> 
     </header> 
     <section id="main"> 
      @RenderBody() 
     </section> 
     <footer> 
     </footer> 
    </div> 
</body> 
</html> 

代碼爲的AccountController登錄行動

[HttpPost] 
     public ActionResult LogOn(LogOnModel model, string returnUrl) 
     { 
      if (ModelState.IsValid) 
      { 
       if (Membership.ValidateUser(model.UserName, model.Password)) 
       { 
        FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); 
        if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") 
         && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) 
        { 
         return Redirect(returnUrl); 
        } 
        else 
        { 
         return RedirectToAction("Index", "Home"); 
        } 
       } 
       else 
       { 
        ModelState.AddModelError("", "The user name or password provided is incorrect."); 
       } 
      } 

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

代碼ApplicationViewPage類

public abstract class ApplicationViewPage<T> : WebViewPage<T> 
    { 
     protected override void InitializePage() 
     { 
      SetViewBagDefaultProperties(); 
      base.InitializePage(); 
     } 

     private void SetViewBagDefaultProperties() 
     { 
      ViewBag.LayoutModel = new LayoutModel(Request.ServerVariables["SERVER_NAME"]); 
     } 

    } 

上面的代碼讓我有一個ViewBag .LayoutModel在每個頁面中保存我的LayoutModel類的一個實例。

這裏是我的LayoutModel類

public class LayoutModel 
    { 
     public string LayoutFile { get; set; } 
     public string IpsTop { get; set; } 
     public string IpsBottom { get; set; } 
     public string ProfileTop { get; set; } 
     public string ProfileBottom { get; set; } 

     public LayoutModel(string hostname) 
     { 
      switch (hostname.ToLower()) 
      { 
       default: 

        LayoutFile = "~/Views/Shared/_BnlLayout.cshtml"; 
        IpsBottom = "~/Template/_BnlIpsBottom.cshtml"; 
        IpsTop = "~/Template/_BnlTop.cshtml"; 
        ProfileTop = "~/Template/_BnlProfileTop.cshtml"; 
        break; 

       case "something.com": 
        LayoutFile = "~/Views/Shared/_Layout.cshtml"; 
        IpsBottom = "~/Template/_somethingBottom.cshtml"; 
        IpsTop = "~/Template/_somethingTop.cshtml"; 
        ProfileTop = "~/Template/_somethingProfileTop.cshtml"; 
        break; 
      } 
     } 
    } 

代碼下面是代碼來查看

@{ 
    ViewBag.Title = "PageTitle"; 
    Layout = @ViewBag.LayoutModel.LayoutFile; 
} 
@using (Html.BeginForm()) 
{ 
    <span class="error">@ViewBag.ErrorMessage</span> 
    <input type="hidden" name="Referrer" id="Referrer" value="@ViewBag.Referrer" /> 
    html stuff here  
} 

,請參閱以下問題的更多細節。確保你修改你的web.config,如下所述:How to set ViewBag properties for all Views without using a base class for Controllers?

+0

@atbebtg - 所以基本上只使用部分意見,並與@ Html.Partial(使其)佈局的內部? – Dimskiy 2011-05-03 17:20:21

+0

是啊,只要使用局部視圖,並做@ Html.Partial() – atbebtg 2011-05-03 17:22:44

+0

如果它是一塊數據的即將進行元素?像CSS文件的路徑或什麼? – Dimskiy 2011-05-03 17:26:47

1

除了atbebtg的回答,爲了渲染東西,你要利用Razor的部分支持。部分被命名爲模板化的HTML片段,可以在視圖中定義並在佈局適合的佈局中呈現。在佈局中,您可以撥打@RenderSection("wellKnownSectionName"),並在使用佈局的視圖中聲明@section wellKnownSectionName { <link rel="stylesheet" href="@UserStylesheetUrl" /><script type="text/javascript" src="@UserScriptUrl"> }。通常你想描述名字的意思,比如「documentHead」。

更新: 如果您在每個視圖上呈現相同的模板化HTML,它將轉而進入佈局。 (由於您的佈局包含HEAD和BODY標籤,因此您可以將相應的代碼添加到HEAD標籤中)。您只需確保通過ViewBag/View.Model從控制器傳遞佈局所需的信息/ ViewData的。所以,你的佈局將包括此:

<head> 
    <link rel="stylesheet" href="/css/@ViewBag.UserName/.css"/> 
</head> 

和您的控制器將包括填充ViewBag.UserName邏輯:

ViewBag.UserName = Session["UserName"]; 

(理想情況下,你可以使用一個強類型的視圖模式,我建議你避免使用Session來做任何事情,因爲它的好處與其他選擇相比是很小的,並且對架構造成很大的代價......相反,我只是建議在包含用戶名或其他內容的瀏覽器上存儲一些加密的cookie,您可以使用它每個頁面加載以從緩存/ db /服務檢索用戶對象。)

+0

感謝一個新的類!但是,如果所有視圖的數據都是相同的呢?我不想有@section wellKnownSection .....在每個視圖上使用相同的邏輯來呈現相同的數據。我寧願在一個地方有這個邏輯。 – Dimskiy 2011-05-03 18:49:41

+0

好的,所以我同意會話,並不完全同意cookie。但是你說的是什麼控制器? 元素在佈局中定義。佈局沒有控制器。某種基地/共享控制器? (P.S.我實際上想過使用自定義URL助手作爲我的例子,用CSS URLs。現在想不到任何其他數據會進入:).....) – Dimskiy 2011-05-03 23:08:51