Adding a view

By Rick Anderson

In this section you’re going to modify the HelloWorldController class to use Razor view template files to cleanly encapsulate the process of generating HTML responses to a client.

You’ll create a view template file using Razor. Razor-based view templates have a .cshtml file extension, and provide an elegant way to create HTML output using C#. Razor seamlessly blends C# and HTML, minimizing the number of characters and keystrokes required when writing a view template, and enables a fast, fluid coding workflow.

Currently the Index method returns a string with a message that is hard-coded in the controller class. Change the Index method to return a View object, as shown in the following code:

public IActionResult Index()
{
    return View();
}

The Index method above uses a view template to generate an HTML response to the browser. Controller methods (also known as action methods) such as the Index method above, generally return an IActionResult (or a class derived from ActionResult), not primitive types like string.

  • Right click on the Views folder, and then Add > New Folder and name the folder HelloWorld.
  • Right click on the Views/HelloWorld folder, and then Add > New Item.
  • In the Add New Item - MvcMovie dialog
    • In the search box in the upper-right, enter view
    • Tap MVC View Page
    • In the Name box, keep the default Index.cshtml
    • Tap Add
../../_images/add_view.png

Replace the contents of the Views/HelloWorld/Index.cshtml Razor view file with the following:

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

Navigate to http://localhost:xxxx/HelloWorld. The Index method in the HelloWorldController didn’t do much work; it simply ran the statement return View();, which specified that the method should use a view template file to render a response to the browser. Because you didn’t explicitly specify the name of the view template file to use, MVC defaulted to using the Index.cshtml view file in the /Views/HelloWorld folder. The image below shows the string “Hello from our View Template!” hard-coded in the view.

../../_images/hell_template.png

If your browser window is small (for example on a mobile device), you might need to toggle (tap) the Bootstrap navigation button in the upper right to see the to the Home, About, and Contact links.

../../_images/1.png

Changing views and layout pages

Tap on the menu links (MvcMovie, Home, About). Each page shows the same menu layout. The menu layout is implemented in the Views/Shared/_Layout.cshtml file. Open the Views/Shared/_Layout.cshtml file.

Layout templates allow you to specify the HTML container layout of your site in one place and then apply it across multiple pages in your site. Find the @RenderBody() line. RenderBody is a placeholder where all the view-specific pages you create show up, “wrapped” in the layout page. For example, if you select the About link, the Views/Home/About.cshtml view is rendered inside the RenderBody method.

Passing Data from the Controller to the View

Before we go to a database and talk about models, though, let’s first talk about passing information from the controller to a view. Controller actions are invoked in response to an incoming URL request. A controller class is where you write the code that handles the incoming browser requests, retrieves data from a database, and ultimately decides what type of response to send back to the browser. View templates can then be used from a controller to generate and format an HTML response to the browser.

Controllers are responsible for providing whatever data or objects are required in order for a view template to render a response to the browser. A best practice: A view template should never perform business logic or interact with a database directly. Instead, a view template should work only with the data that’s provided to it by the controller. Maintaining this “separation of concerns” helps keep your code clean, testable and more maintainable.

Currently, the Welcome method in the HelloWorldController class takes a name and a ID parameter and then outputs the values directly to the browser. Rather than have the controller render this response as a string, let’s change the controller to use a view template instead. The view template will generate a dynamic response, which means that you need to pass appropriate bits of data from the controller to the view in order to generate the response. You can do this by having the controller put the dynamic data (parameters) that the view template needs in a ViewData dictionary that the view template can then access.

Return to the HelloWorldController.cs file and change the Welcome method to add a Message and NumTimes value to the ViewData dictionary. The ViewData dictionary is a dynamic object, which means you can put whatever you want in to it; the ViewData object has no defined properties until you put something inside it. The MVC model binding system automatically maps the named parameters (name and numTimes) from the query string in the address bar to parameters in your method. The complete HelloWorldController.cs file looks like this:

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
    public class HelloWorldController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Welcome(string name, int numTimes = 1)
        {
            ViewData["Message"] = "Hello " + name;
            ViewData["NumTimes"] = numTimes;

            return View();
        }
    }
}

The ViewData dictionary object contains data that will be passed to the view. Next, you need a Welcome view template.

  • Right click on the Views/HelloWorld folder, and then Add > New Item.
  • In the Add New Item - MvcMovie dialog
    • In the search box in the upper-right, enter view
    • Tap MVC View Page
    • In the Name box, enter Welcome.cshtml
    • Tap Add

You’ll create a loop in the Welcome.cshtml view template that displays “Hello” NumTimes. Replace the contents of Views/HelloWorld/Welcome.cshtml with the following:

@{
    ViewData["Title"] = "About";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
    {
        <li>@ViewData["Message"]</li>
    }
</ul>

Save your changes and browse to the following URL:

http://localhost:xxxx/HelloWorld/Welcome?name=Rick&numtimes=4

Data is taken from the URL and passed to the controller using the MVC model binder . The controller packages the data into a ViewData dictionary and passes that object to the view. The view then renders the data as HTML to the browser.

../../_images/rick1.png

In the sample above, we used the ViewData dictionary to pass data from the controller to a view. Later in the tutorial, we will use a view model to pass data from a controller to a view. The view model approach to passing data is generally much preferred over the ViewData dictionary approach.

Well, that was a kind of an “M” for model, but not the database kind. Let’s take what we’ve learned and create a database of movies.