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
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) {
Welcome @User.Identity.Name!
[ @Html.ActionLink("Log Off", "LogOff", "Account") ]
}
else {
@:[ @Html.ActionLink("Log On", "LogOn", "Account") ]
}
User.Identity is part of the aspnet Membership provider.
Code for the _Layout.cshtml
@ViewBag.Title
Test
@Html.Partial("_LogOnPartial")
@RenderBody()
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 : WebViewPage
{
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())
{
@ViewBag.ErrorMessage
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?