Since WebMatrix and ASP.NET MVC Razor views share the Razor syntax to create views, the easiest way to create a view in the demo ASP.NET MVC blog site is to copy the markup we already created in the WebMatrix example. First, however, you need to create a new view to contain the copied markup.
The ASP.NET MVC platform adds several convenient and helpful extensions to the Visual Studio IDE. One of the extensions adds two new context menu items, named Add View and Go to View, that show up when you right-click on a controller action. These menu items make it very easy to create and navigate to the views associated with an action.
The Add View context menu item is the quickest and easiest way to
create a new view. To create a new view for the Index
action in the HomeController of the demo blog application, simply
right-click anywhere within the Index
action, and
then choose Add View. This should pop up the Add View Wizard.
The Add View Wizard prepopulates several of the fields by using conventions. In this case, the value in the prepopulated “View name” field is “Index,” the name of the controller action from which we clicked on the Add View context menu. The “View engine” field lets developers choose which syntax to use for creating views. The default view engine is “Razor (CSHTML),” which means the Razor C# syntax (as opposed to, say, the Razor Visual Basic .NET syntax).
Ignore the rest of the fields in the wizard; later sections of the book will revisit them in detail. For now, just click the Add button and let’s write a view!
Clicking the Add button tells Visual Studio to create a new view file for you at the appropriate location within the project. Figure 4-4 shows the contents of the project’s Views folder after the Add View dialog executes.
As you can see, the Views folder contains child folders named Home
and Shared. Why are these folders named this way? You guessed it: yet
another convention! By default, ASP.NET MVC assumes that all website
views exist somewhere underneath the Views folder. Further, ASP.NET MVC
looks for child folders underneath the root Views folder with folder
names corresponding to the names of controllers in the application.
Using all of this information—along with the information we provided—the
Add View dialog chose to create a file named
Index.cshtml in a new folder under the root Views
folder named Home (corresponding to the HomeController
controller class the Add View
menu action originated from). Leveraging the power of conventions,
Visual Studio was able to do all of this with just two clicks!
Why the .cshtml file extension?
In the course of rendering a view, the ASP.NET MVC runtime will use the view’s file extension to determine how to compile the markup in the view. For instance, ASP.NET MVC can safely assume that a file with the .aspx extension uses the Web Forms syntax, whereas a view with the .cshtml extension contains Razor markup. Both ASP.NET MVC Razor views and WebMatrix Web Pages use the .cshtml extension for Razor views that leverage the C# language and .vbhtml for Razor views that leverage Visual Basic .NET. ASP.NET MVC supports both languages equally—they can even be used together in the same project!
After creating the new file, replace the entire contents of this new view with this markup:
<h1>My Blog</h1> @foreach(var post in Model) { <div> <h3>@post.Title</h3> <div>@post.Body</div> </div> }
This should look familiar; it’s very similar to the markup you
used to create the home page in the WebMatrix blog site. The biggest
difference is that, instead of pulling the posts data from the database,
the markup iterates over the View’s Model
property, which represents the model
data passed to the View from the Controller in Data access with Entity Framework code first.
At this point, you have everything in place to generate a web
page: the Controller is retrieving data from the database and passing
that data to the View, which the View can then use to render dynamic
HTML. To see it in action, hit F5
to
execute the website. If you have data in the Posts database, it should
render something similar to the following:
<h1>My Blog</h1> <div> <h3>Test Post #1</h3> <div>This is the first test post</div> </div> <div> <h3>Test Post #2</h3> <div>This is the second test post</div> </div> <div> <h3>Test Post #3</h3> <div>This is the third test post</div> </div>
The Model
property present in
the WebViewPage
base class from which
all ASP.NET MVC views derive is dynamically-typed by default. This means
that it uses .NET 4.0’s dynamic type, delaying the specification of the
type until runtime. Thus, Controller Actions and other parts of the
ASP.NET MVC framework can populate this field with any type and the
views can apply the concept of “duck-typing” to work with a variety of
types. As long as the model object contains the properties with the name
that the view expects, any type will do!
If this “fast and loose” approach concerns you, you are in good
company. You are also in luck: ASP.NET MVC adds the @model
keyword to Razor’s vernacular, which
allows views to specify the type of their Model
property. The @model
keyword follows the syntax @model Class Name
.
To show the @model
keyword in
action, let’s modify the previous example and turn it into a
strongly-typed view by specifying a @model
:
- A strongly-typed view
@model IEnumerable<MvcRazorBlog.Models.Post> @section Header { <h1>My Blog</h1> } @foreach(var post in Model) { @RenderPage("~/Posts/_Post.cshtml", new { post = post }) }
And just like that, the Model
property is now strongly-typed as an IEnumerable<MvcRazorBlog.Models.Post>
,
ready for use without additional casting.
By default, all ASP.NET MVC Razor views inherit from the System.Web.Mvc.WebViewPage
class. However,
views that specify a model type using the @model
keyword inherit from the generic
version of WebViewPage
: System.Web.Mvc.WebViewPage<TModel>
. With
the exception of a few Razor keywords outlined in the first chapter, the
bulk of ASP.NET MVC’s view-related functionality (such as the @Html
and @Url
helpers) exists as properties or
extension methods off of the WebViewPage
class.
What the @model
keyword
actually does is tell ASP.NET MVC to add a generic parameter to the base
page type. In other words, an ASP.NET MVC view without the @model
keyword derives from the WebViewPage
base class like so:
public class Index : WebViewPage { /* Class stuff in here */ }
But when the @model
keyword is
applied, as in the previous example, Razor adds the specified type as a
generic parameter to the generated class. For example:
@model IEnumerable<MvcRazorBlog.Models.Post>
will generate the view:
public class Index : WebViewPage<IEnumerable<MvcRazorBlog.Models.Post>> { /* Class stuff in here */ }
Get Programming Razor now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.