CHAPTER 3 VIEWS
public ActionResult Index()
{
return View("~/Views/Example/Index.cshtml");
}
When using the tilde syntax, you must supply the file extension of the view because this bypasses the view engine's internal lookup mechanism for finding views.
public ActionResult List()
{
var albums = new List<Album>();
for (int I = 0; i < 10; i++)
{
albums.Add(new Album {Title = "Album " + i});
}
return View(albums);
}
indicate to the view what type of model is using the @model declaration. Note that you might need to supply the fully qualified type name (namespace plus type name) of the model type.
@using MvcMusicStore.Models
@model IEnumerable<Album>
<ul>
@foreach (Album p in Model) {
<li>@p.Title</li>
}
</ul>
An even better approach for namespaces, is to declare the namespace in the web.config file within the Views directory:
<system.web.webPages.razor>
…
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="MvcMusicStore.Models" />
</namespaces>
</pages>
</system.web.webPages.razor>
both these values are passed via the ViewDataDictionary.
all data is passed from the controllers to the views via a ViewDataDictionary
The ViewBag is a dynamic wrapper around ViewData. It allows you to set values as follows:
ViewBag.CurrentTime = DateTime.Now;
Thus, ViewBag.CurrentTime is equivalent to ViewData["CurrentTime"].
you cannot pass in dynamic values as parameters to extension methods. If any parameter is dynamic, compilation will fail. For example, this code will always fail:
@Html.TextBox("name", ViewBag.Name)
To work around this, either use ViewData["Name"] or cast the value to a specific type:
(string)ViewBag.Name
Because you can only have one model object in ViewData, using this to pass a specific class to the view is convenient. This allows your view to specify the class it is expecting the model object to be, which means you can take advantage of strong typing.
One easy approach to displaying extra data that isn't a part of your view's main model is to simply stick that data in the ViewBag.
One recommended approach is to write a custom view model class. You can think of a view model as a model that exists just to supply information for a view.
For example, if you had a shopping cart summary page that needed to display a list of products, the total cost for the cart, and a message to the user, you could create the ShoppingCartViewModel class, shown as follows:
public class ShoppingCartViewModel {
public IEnumerable<Product> Products { get; set; }
public decimal CartTotal { get; set; }
public string Message { get; set; }
}
Now you can make a view strongly typed to this model, using the following @model directive:
@model ShoppingCartViewModel
THE RAZOR VIEW ENGINE
What Is Razor?
Code Expressions
HTML Encoding
Code Blocks
Razor Syntax Samples
Implicit Code Expression
<span>@model.Message</span>
Explicit Code Expression
<span>1 + 2 = @(1 + 2)</span>
Unencoded Code Expression
<span>@Html.Raw(model.Message)</span>
Code Block
@{
int x = 123;
string y = "because.";
}
Combining Text and Markup
@foreach (var item in items) {
<span>Item @item.Name.</span>
}
Mixing Code and Plain Text
@if (showMessage) {
<text>This is plain text</text>
}
@if (showMessage) {
@:This is plain text.
}
Escaping the Code Delimiter
The ASP.NET Twitter Handle is @aspnet
The ASP.NET Twitter Handle is @@aspnet
Server-Side Comment
Calling a Generic Method
Layouts
<!DOCTYPE html>
<html>
<head><title>@ViewBag.Title</title></head>
<body>
<h1>@ViewBag.Title</h1>
<div id="main-content">@RenderBody()</div>
</body>
</html>
Use the layout:
@{
Layout = "~/Views/Shared/SiteLayout.cshtml";
ViewBag.Title = "The Index!";
}
<p>This is the main content!</p>