Reputation: 8651
Why sometimes @ViewBag.Title
contains the right page title while @Page.Title
is null? We are debugging our View/Layout code and we noticed this difference.
Thanks.
Upvotes: 1
Views: 8997
Reputation: 157
When your are using asp.Net MVC you have a few tools you can use to get data to your page.
Each one of theese has their own use cases The example we will be using is a basic List and update View For a collection of companies
The Model
The model Should be used whenever you have a defined dataset being sent to a view and should contain the primary data for the page and usally a model is specific to a page or controller.
The ViewBag
The ViewBag should be used whenever you need to send general data to a page that is not defined on the model or data that is used across your view tree.
Temp Data
Temp Data is as the name states storage for temporary data this should be used in cases where you are unsure if the data will reach its destination or when you want to pass data between actions without adding parameters.
Cookies
Cookies are like Global variables the host data across your entire application.
Session
Sessions like cookies are global variables but differ in their lifetime sessions can be used for things like Storing form data between requests dont use session to do this rather use something like http://garlicjs.org/
Lets look at the example We have the following ViewModel
public class Company
{
public int? id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The layout page looks like this
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
//This looks for the Title property on the ViewBag and inserts it in the title tags
<title>@ViewBag.Title</title>
</head>
<body>
@Html.Action("Header", "PageElements")
@RenderBody()
</body>
</html>
The Header Action on the PageElements Contoller looks like this
public PartialViewResult Header()
{
ViewBag.CurrentLink = HttpContext.Current.Request.Cookies["CurrentLink"];
return PartialView();
}
The Header Partial View looks like this
<header>
<ul>
<li class="@(ViewBag.CurrentLink == "Home" ? "Current" : "")">
@Html.ActionLink("Home", "Index", "Home")
</li>
<li class="@(ViewBag.CurrentLink == "Companies" ? "Current" : "")">
@Html.ActionLink("Companies", "Index", "Companies")
</li>
</ul>
</header>
The controller action for update looks like this
public ViewResult Update(int id)
{
//Gets a company from the database
var model = db.GetCompany(id);
//Sets The Title property on the ViewBag to Update : CompanyName
ViewBag.Title = String.Format("Update : {0}", model.Name);
//Sends the company to the view
return View(model);
}
The update view looks like this
@model Application.Models.Company
@{
Layout = "_layout.cshtml";
}
@using (Html.BeginForm())
{
@Html.HiddenFor(model => Model.id)
@Html.LabelFor(model => Model.Name)
@Html.TextBoxFor(model => Model.Name)
@Html.LabelFor(model => Model.Description)
@Html.TextAreaFor(model => Model.Description)
<button>Submit</button>
}
The Post Action for Update looks like this
[HttpPost]
public ActionResult Update(Company model)
{
//Attempts to update the model
if (model.Update())
{
//Set the message to update succeeded
TempData["Message"] = String.Format("{0} Successfully updated");
}
else
{
//Set the message to update failed
TempData["Message"] = String.Format("{0} filed to update");
}
return RedirectToAction("Index");
}
The Controller action for companies looks like this
public ViewResult Index()
{
//Index is the entrypoint for companies so we set the currentlink to companies while we are in companies
HttpContext.Current.Request.Cookies["CurrentLink"] = "Companies";
//Gets the success or failure message from the temp data
ViewBag.Message = TempData["Message"];
//Sets The Title property on the ViewBag to List of companies
ViewBag.Title = "List of companies";
var model = db.GetAllCompanies();
return View(model);
}
The view for the list looks like this
@model IEnumrable<Application.Models.Company>
@{
Layout = "_layout.cshtml";
}
<span>@ViewBag.Message</span>
<ul>
@foreach (var company in Model)
{
<li>@company.Name : @company.Description @Html.AnchorLink("Edit", "Update", new { company.id}) </li>
}
</ul>
Lets discuss how the flow of this application works
We used the Model to send Specific data to the view. We used the ViewBag to send General data to the view and the layout. We used TempData to pass data between actions without using parameters. We used Cookies to Store data that wouldn't change for a while.
Upvotes: 9
Reputation: 38608
The correct is using ViewBag.Title
, because it is on the context of your ViewBag
property of your View
while Page.Title
is something that comes from asp.net webforms. That is the reason why Page.Title
is null, there is no context for it.
Upvotes: 4