How can I write dynamic data to page layout in MVC 3 Razor?

前端 未结 2 545
眼角桃花
眼角桃花 2021-02-02 14:44

I have MVC 3 C# project with Razor engine. What are the ways and, I guess, the best practices to write dynamic data to the _Layout.cshtml?

For example, maybe I\'d like

相关标签:
2条回答
  • 2021-02-02 15:03

    In addition to atbebtg's answer, to render stuff into the head, you want to leverage Razor's section support. Sections are named fragments of templated HTML that can be defined in views and rendered in the layout, where the layout sees fit. In the layout, you call @RenderSection("wellKnownSectionName") and in the view that uses the layout, you declare @section wellKnownSectionName { <link rel="stylesheet" href="@UserStylesheetUrl" /><script type="text/javascript" src="@UserScriptUrl"> }. Usually you want to describe the intention of the section in its name, such as "documentHead".

    Update: If you're rendering the same templated HTML on every view, it would instead go into the layout. (Since your layout includes the HEAD and the BODY tags, you can just add the appropriate code to the HEAD tag their.) You just need to make sure you pass the information necessary for the layout from the controller via the ViewBag/View.Model/ViewData. So your layout would include this:

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

    and your controller would include the logic to populate ViewBag.UserName:

    ViewBag.UserName = Session["UserName"];
    

    (Ideally you would use a strongly-typed view model and I would recommend you abstain from using Session for anything, since its benefits are small compared to alternatives and comes at a big cost to architecture... instead I would simply recommend storing some encrypted cookie on the browser that contains a username or something, which you can use on each page load to retrieve the user object from cache/db/service.)

    0 讨论(0)
  • The default internet application created by visual studio use _LogOnPartial.cshtml to do exactly this.

    The user Name value is set in the LogOn action of the HomeController

    Code for _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 is part of the aspnet Membership provider.

    Code for the _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>
    

    Code for the AccountController Logon Action

    [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);
            }
    

    Code for ApplicationViewPage class

    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"]);
            }
    
        }
    

    The above code allow me to have a ViewBag.LayoutModel that hold an instance of my LayoutModel class in every page.

    Here is a code for my LayoutModel class

    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;
                }
            }
        }
    

    Here is the code to the View

    @{
        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       
    }
    

    Refer to the following question for more detail. Make sure you modify your web.config as described there: How to set ViewBag properties for all Views without using a base class for Controllers?

    0 讨论(0)
提交回复
热议问题