A Layout file knows nothing about the Views (.cshtml files) that use it, and the Views also know nothing about the Layout file, except its name.
The proper way to connect the two is as follows:
(1) Have _Layout.cshtml contain a @RenderBody()
statement. This is where the output that is generated by the Views will appear.
(2) Have your View-file reference the layout file by its name, also preferrably make it use a Model
class, and make it render partial HTML:
// file Views/Location/MyLocation.cshtml
@model YourProject.Models.Location // See part (3) below
@{
Layout = "_Layout";
}
<h2>My Location</h2>
<div>
City: @(Model.City)
</div>
(3) Define the model class:
// file Models/Location.cs
namespace YourProject.Models
{
public class Location
{
public string City { get; set; }
}
}
(4) Have the Action-method in the Controller create a Model object, and send it to the View:
// file Controllers/LocationController.cs
namespace YourProject.Controllers
{
public class LocationController : Controller
{
public IActionResult MyLocation()
{
var model = new Location { City = "NYC" };
return View(model); // This will start MyLocation.cshtml and pass 'model' as a parameter into it
}
}
}
More info here:
As an alternative you could use ViewBag
. You can then omit the Location
Model class, but you will also lose all the advantages of Intellisense and compile-time validity checking.
// file Views/Location/MyLocation.cshtml
@{
Layout = "_Layout";
}
Location: @(ViewBag.Location) <i>(from ViewBag)</i>
// file Controllers/LocationController.cs
namespace YourProject.Controllers
{
public class LocationController : Controller
{
public IActionResult MyLocation()
{
ViewBag.Location = "NYC";
return View(); // This will start MyLocation.cshtml without a 'model'.
}
}
}
You can use a ViewBag approach, a Model approach, or even combine the two.
You can also use ViewBag in the _Layout file, but then you have to make sure that every Controller action method supplies the value in ViewBag
because it is not preserved between calls.