如何在MVC 3 Razor中将动态数据写入页面布局?

我有Razor引擎的MVC 3 C#项目。 有什么方法,我想,将动态数据写入_Layout.cshtml的最佳做法是什么?

例如,也许我想在我的网站的右上角显示用户名,并且该名称来自会话,数据库或其他任何基于用户登录的内容。

更新:我也在寻找将某些数据渲染到布局元素的良好实践。 例如,如果我需要根据登录用户的凭据呈现特定的CSS文件。

(对于上面的例子,我想过使用Url Helpers。)

visual studio创建的默认Internet应用程序使用_LogOnPartial.cshtml来完成此操作。

用户名值在HomeController的LogOn操作中设置

_LogOnPartial.cshtml的代码

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

User.Identity是aspnet成员资格提供者的一部分。

_Layout.cshtml的代码

     @ViewBag.Title      

Test

@Html.Partial("_LogOnPartial")
@RenderBody()

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 : WebViewPage { 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; } } } 

这是View的代码

 @{ ViewBag.Title = "PageTitle"; Layout = @ViewBag.LayoutModel.LayoutFile; } @using (Html.BeginForm()) { @ViewBag.ErrorMessage  html stuff here } 

有关更多详细信息,请参阅以下问题。 确保修改web.config,如下所述: 如何为所有视图设置ViewBag属性而不使用控制器的基类?

除了atbebtg的答案,要想把东西放到头脑中,你想要利用Razor的部分支持。 节被命名为模板化HTML的片段,可以在视图中定义并在布局中呈现,布局认为适合。 在布局中,您调用@RenderSection("wellKnownSectionName")并在使用布局的视图中声明@section wellKnownSectionName { 。 通常,您希望在其名称中描述该部分的用意,例如“documentHead”。

更新:如果您在每个视图上呈现相同的模板化HTML,则会转到布局中。 (由于您的布局包含HEAD和BODY标记,您只需将相应的代码添加到HEAD标记中即可。)您只需确保通过ViewBag / View.Model从控制器传递布局所需的信息。 / ViewData的。 所以你的布局包括:

    

并且您的控制器将包含填充ViewBag.UserName的逻辑:

 ViewBag.UserName = Session["UserName"]; 

(理想情况下,你会使用一个强类型的视图模型,我建议你不要使用Session做任何事情,因为它的优点与替代品相比很小,而且建筑成本很高......相反,我只是建议存储一些加密的浏览器上包含用户名或内容的cookie,您可以在每个页面加载时使用它来从cache / db / service检索用户对象。)