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 to display user's name in the upper right corner of my website, and that name is coming from Session, DB, or whatever based on what user is logged in.
UPDATE: I'm also looking for a good practice on rendering certain data into the element of the Layout. For example, if I need to render a specific CSS file depending on the logged-in user's credentials.
(For the example above, I thought of using Url Helpers.)
To pass the strongly typed data from Controller to View using ViewBag, we have to make a model class then populate its properties with some data and then pass that data to ViewBag with the help of a property. And then in the View, we can access the data of model class by using ViewBag with the pre-defined property.
Right click the Views\HelloWorld folder and click Add, then click MVC 5 View Page with Layout (Razor). In the Specify Name for Item dialog box, enter Index, and then click OK. In the Select a Layout Page dialog, accept the default _Layout. cshtml and click OK.
You can add support for Pages to any ASP.NET Core MVC app by simply adding a Pages folder and adding Razor Pages files to this folder.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With