Chapter 2

Employing the Razor Markup Language

IN THIS CHAPTER

Bullet Understanding how Razor fits into the picture

Bullet Working with variables in Razor

Bullet Making decisions using Razor

Bullet Storing and cycling through data

As mentioned in Chapter 1 of this minibook, Razor is Microsoft’s language for implementing dynamic web content. While Chapter 1 shows how to create static content, most websites today use dynamic content so that updating them is easier. Using Razor is sort of like mixing C#, HTML, and some older technologies reminiscent of Active Server Pages (ASP) (https://docs.microsoft.com/en-us/troubleshoot/iis/asp-support-windows). The first part of this chapter discusses how this mix occurs and shows you some basics.

As with C#, any discussion of Razor needs to begin with using variables to store data. This means understanding the Razor data types, how to work with operators, and how to convert one data type to another. The information you obtained in Book 1, “The Basics of C# Sharp Programming,” and especially in Chapters 2 through 4, will help you in this minibook.

The next three parts of the chapter discuss how to work with and manipulate data using a combination of logical statements, arrays, and loops. If you’ve read through Chapters 5 through 7 of Book 1, you’ll find the information in these three parts of the chapter quite familiar because Razor is based on C# and follows the C# rules. However, there are differences between Razor and C# that these parts of the chapter help point out.

Remember You don’t have to type the source code for this chapter manually. In fact, using the downloadable source is a lot easier. You can find the source for this chapter in the CSAIO4D2EBK06CH02 folder of the downloadable source. See the Introduction for details on how to find these source files.

Avoiding Nicks from Razor

Trying to comprehend a new technology can be difficult, and the learning curve often feels artificially steep. In fact, it feels like those early days of shaving when being unfamiliar with the razor makes one nick their skin constantly. The following sections help you avoid the nicks by bringing the learning curve down a little. To make this process easier, create an ASP.NET Core Web App using the template wizard and insights contained in the “Creating a basic app using the ASP.NET Core Web App” section of Chapter 1 of this minibook. You don't need to add anything to the resulting project; it’s just helpful to have the files available for viewing. Use the .NET 3.1 (Long-term Support) framework and select None for Authentication type; deselect the Configure for HTTPS option, and select the Enable Razor runtime-compilation option. As an alternative, you can use the RazorPageOverview example found in the downloadable source.

Comparing Razor to its predecessors

There is a long list of technologies that precede Razor, representing a sort of a flavor-of-the-year march toward where the technology sits today. It starts with classic Active Server Pages (ASP), moves through various incarnations of that technology, through Model-View-Controller (MVC), to Razor today. If you’ve been a developer for long, the subtle but continuing changes in technology could drive you a bit nuts. In fact, when you go online to various tutorial sites such as W3Schools (https://www.w3schools.com/asp/default.ASP), even they have a hard time condensing the technology and making it easier to understand. When you start looking at ASP.NET tutorials (https://www.tutorialspoint.com/asp.net/asp.net_first_example.htm), you begin to see bits and pieces of what eventually became Razor. For example, both use the @page directive (look at the top of Index.cshtml in your project to see this directive), but Razor uses it in a slightly different manner, which is the source of much of the confusion out there about Razor.

The comparison you see most often is between MVC and Razor. Microsoft currently recommends using Razor to reduce complexity (https://docs.microsoft.com/dotnet/architecture/porting-existing-aspnet-apps/comparing-razor-pages-aspnet-mvc). Note that there is an MVC-like approach in Razor, except that Microsoft uses different terms for the various components because using different terms makes technology look new and shiny. So, the MVC action is now a handler, the MVC ViewModel is now a PageModel, and the view is now a Razor Page. When working in MVC, these elements appear in three different locations and you need to modify them individually, which makes MVC error prone because people forget to do things unless they have a string tied around their finger. When working with Razor, the handler and PageModel appear in a single file, while the view appears in a separate file, all under the Pages folder in the project. Here are some other differences between MVC and Razor:

  • Simpler pages: A Razor page does have some connectivity to other files, but it's very close to a Web Forms setup in that you have the nonshared content in a single .cshtml file with a code-behind file.
  • Focus: Many developers view Razor as the optimal solution for HTML views. They see MVC as an optimal solution for a Representational State Transfer (REST) API or a Service-Oriented Architecture (SOA). The technology you choose depends on the sort of website you want to create. Razor is typically the simple solution for simple problems.
  • Less code: In comparing similar coding examples between Razor and MVC, you often find that the Razor code is a little shorter (not much) and a little simpler. However, little differences tend to pile up when you’re working on a website of any size and complexity.

Warning One of the issues that will cause most developers woe is the fact that Visual Studio doesn’t come with a designer for Razor pages. In Book 5, Chapter 2 you see a process for working with XAML to create WPF applications. To create an application, you drag and drop components onto the canvas. Book 5, Chapter 5 shows the same process for UWP applications. Unfortunately, when working with ASP.NET Core, you’re left to write code manually. The only website development that Visual Studio 2022 offers with a designer is the older Web Forms templates, which require a special setup, as described in the “Gaining access to the Web Forms templates” sidebar.

Considering the actual file layout

A Razor website uses a number of files that may seem a little daunting at first, but they make sense after you take them apart rather than attempt to view them as a whole. Here is the list of files for the website in the order in which they’re typically used to create the presentation:

  • Program.cs: Contains the Main() method and application startup code. This code includes the creation of a IHostBuilder object, webBuilder, which actually starts the website using the Startup class found in Startup.cs.
  • Startup.cs: Defines the website's underlying configuration. This is where the application adds Razor pages to the site and determines how those pages will interact. The “Developing a Basic Web App” section of Chapter 1 of this minibook shows you some of what goes on in the Startup class, such as adding UseEndpoints() calls and substituting calls to app.UseDefaultFiles(); and app.UseStaticFiles(); to support the use of static HTML files on a site. The calls made within this class determine the characteristics of the website interactions.
  • _ViewImports.cshtml: Specifies the application imports, Razor page namespace, and helpers used to render the Razor pages (@addTagHelper). You can read more about tag helpers at https://docs.microsoft.com/aspnet/core/mvc/views/tag-helpers/intro.
  • _ViewStart.cshtml: Declares which layout page to use for a website. The use of this file eliminates the need to declare the layout page in every content page for the website, reducing potential errors. You can use this feature to change the entire feel of a website with a single coding change.
  • _ValidationScriptsPartial.cshtml: Contains pointers to the scripts used to validate the Razor page content. You see older websites that have the scripts actually included in this file. Newer versions of ASP.NET core pages include references to external files to use for validation purposes, which makes maintaining the setup easier.
  • _Layout.cshtml: Determines the overall appearance of the Razor pages. Consequently, when you open this file, you see what appears to be an entire HTML page with special inclusions for specific page content, such as @ViewData["Title"], which determines the page title. This is also where you find common page elements, such as the navbar used to move between pages. However, this file doesn't contain any actual content — it’s simply the layout used to contain the specific page layout.
  • index.cshtml: Defines the first content page for a website. In all cases, the content appears within a layout specified by the layout document, which is usually _Layout.cshtml.
  • index.cshtml.cs: Contains the code-behind for the associated content page. The code-behind performs tasks such as handling user-interface events and performing some types of dynamic page setups. Razor pages are based on the PageModel class (https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.razorpages.pagemodel).

You see other content pages provided with the project that include Privacy.cshtml and Error.cshtml. These additional content pages work the same as index.cshtml, but they're called upon as needed. There is a link from the home page to Privacy.cshtml. The Error.cshtml file is called upon only when there is an error.

Understanding the syntax rules for C#

A Razor page is a combination of elements that include both HTML and code. How you combine the elements depends on what you plan to do. However, all your code will begin with an at sign (@). For example, if you want to add a date to the default Index.cshtml page, you might use the following code shown in bold:

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>It's @DateTime.Now.ToLongDateString()</p>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">
building Web apps with ASP.NET Core
</a>.</p>
</div>

Notice that this paragraph uses a combination of an HTML tag, <p>, plain text, and a call to @DateTime.Now.ToLongDateString(). The date will change every time someone loads the page. After that, however, it remains static. A lot of content falls into this category, and you should use this technique whenever possible to make things simple. The output of this call comes in the following form:

It's Friday, October 15, 2021

Remember Of course, you can create changing content and perform all sorts of other tasks. All the entries for performing code-related tasks on a page begin with @. If you actually need to show the @ sign on a page, you use @@ instead. In that case, Razor views the @@ as an @ and doesn't process the text that comes afterward as code.

There are some special rules for working with code on a Razor page, but the code appears as a form of C# and uses C# syntax rules. You could just as easily get the long date in your C# console application using DateTime.Now.ToLongDateString() as you can when working with Razor. So, it’s important not to overthink how to do things.

Working with some Razor basics

Many sources online (such as https://docs.microsoft.com/aspnet/core/razor-pages/) show lots of ways to write code in Razor, but few of them look at simple tasks, which can mean that they can be quite hard to comprehend. To avoid frustration, you need something easier. The following sections look at two basic tasks that you might perform on any web page.

Making output mundane

The previous section showed a simple way to display the current date on your page. You actually have multiple ways to work with simple kinds of output depending on what you want to do. For example, you can add a field to your code to perform more complex kinds of output like this:

@{
var showString = "This is a string.";
}

You can then use showString in your page like this:

<p id="StringOutput">@showString</p>

The creation of showString can include any level of complexity needed to provide the data required. However, at its root, showString is simply an output that provides online data.

You can also create custom classes to interact with your Razor page. For example, you might create a class like this one in Index.cshtml.cs:

public class CodeBehind
{
public string aString = "This is a code-behind string.";
}

Remember To use this class in your code, you must first create an instance of it like this:

@{
var codeBehind = new CodeBehind();
}

You then use the instance variable, codeBehind, on your page like this:

<p id="StringOutput2">@codeBehind.aString</p>

Tip Notice that you access the CodeBehind class instance variable, aString, through the Razor page instance variable codeBehind. You can access instance methods in the same manner. If your custom class uses static fields or methods, you don't have to create an instance variable. As with any C# code, you can access static fields or methods without creating an instance variable first.

Changing web page data

Sometimes you just need to make a simple change to a web page and don’t really want to create a complex design that will make your friends envious. Web pages are static, unlike applications on desktops that can be as dynamic as they want. Consequently, you need some means of requesting an update from the server or provide client-side code to make the change locally, but the fact is that you need some means of changing the web page content through a request. The easiest way to perform this task using Razor is to create code-behind. In this case, the code appears in Index.cshtml.cs as part of the IndexModel class like this:

public string changingString { get; set; }

public void OnGet()
{
changingString = "This is the changing string.";
}

public void OnPost()
{
changingString = "The string has changed.";
}

The focus of this code is the changingString property, which is set by OnGet() during the initial page request. Whenever your browser requests a new page, the code-behind looks at OnGet() to see whether there's something special to do. Later, when you request a change, you can use the post method in your page code to call on OnPost(), which assigns a new value to changingString. The code in Index.cshtml looks like this:

<p>@Model.changingString</p>
<form method="post">
<button>Click to Change Text</button>
</form>

Mind you, that <form> really is around the individual <button>, not around the page as a whole. Notice that you use @Model.changingString to access changingString. A good many online examples show @changingString, which doesn't work at all (although it might have in the past). The <button> is just a simple HTML button without any sort on onclick handler added to it, so it doesn't look like it should work, but it actually does.

Of course, you might need to provide multiple buttons — imagine that! The simple post method doesn’t work in this case, but you have another option with a very small change. You give the OnPost() method a more specific name, one that has a handler name to go with it. So, the following code has OnPostView1() and OnPostView2():

public void OnPostView1()
{
changingString = "The string has changed.";
}

public void OnPostView2()
{
changingString = "Another Change!";
}

Now you need another method for accessing the methods. You get this method by simply adding the asp-page-handler attribute to the <form> tag, as shown here:

<form asp-page-handler="view1" method="post">
<button>Click to Change Text</button>
</form>
<form asp-page-handler="view2" method="post">
<button>Try Another Change</button>
</form>

Remember The value added to the asp-page-handler attribute is somewhat counterintuitive. Notice that it's just view1 or view2, not OnPostView1 or OnPostView2. The OnPost part of the reference is addressed by the method="post" attribute. If you were to use method="get" instead, the method names in your code-behind would need to be OnGetView1() and OnGetView2() instead. The use of this approach also changes the URL for the page. When a user clicks the first button, the URL changes to http://localhost:18975/?handler=view1. Likewise, when the user clicks the second button, the URL changes to http://localhost:18975/?handler=view2. (Note that the port number, 18975, will vary by system.) The bottom line is that you can have as many buttons as needed on a Razor page and use this simple approach to manage them.

Creating Variables

Variables in Razor follow the same course as variables in C#. You have access to the same data types, the same operators, and so on. However, you may find yourself using them differently. In many cases, variables provide assistance with creating content. For example, you might want to know whether someone is using view1 from the examples earlier in the chapter. In this case, you can simply test the content of changingString and place it in a bool in the Index.cshtml file, like this:

@{
bool isView1 = Model.changingString == "The string has changed.";
}

This sort of test helps you decide how to process information. You can use this sort of testing to change the content of the page after each reload. It helps you do things like decide whether the user is logged into the website or if there is a connection to the database you need. The web page content can change to meet specific demands without having to rely on code-behind to do it.

Keeping Things Logical

The pattern for working with logical statements in Razor is very much the same as working with logical statements in C#, but with a slight twist. As with all code in a .cshtml page, you must precede the logical structure with an @ sign. The following sections discuss the basic logical statements and how to use them as part of a Razor page.

Starting simply by using if

The “Creating Variables” section, earlier in this chapter, discusses how to create variables in Razor. You can use these variables in all sorts of ways, but one of the most common methods is to modify the page appearance to meet specific conditions. The following @if statement uses the isView1 variable created earlier to change the appearance of the page:

@if(isView1)
{
<p>Using View1</p>
}
else
{
<p>Not Using View1</p>
}

Notice that this looks about the same as any other if statement in C#. However, the output is different. In this case, you see that the selection of a particular logical path results in HTML output rather than the execution of code. Also note that the else clause of the if statement lacks the @ sign.

Sleeping at the switch

Razor supports switches, which can save you considerable time typing. Say you create an int named ViewNumber like this:

@{
int ViewNumber;
if (Model.changingString == "This is the changing string.")
ViewNumber = 0;
else if (Model.changingString == "The string has changed.")
ViewNumber = 1;
else
ViewNumber = 2;
}

The if statement appears normal in this case because it appears within an @ block. The code places a value in ViewNumber that corresponds to the current text in changingString. You can use a switch to process ViewNumber, like this:

@switch(ViewNumber)
{
case 0:
<p>Using Original View</p>
break;
case 1:
<p>Using View 1</p>
break;
case 2:
<p>Using View 2</p>
break;
default:
<p>Unrecognized View</p>
break;
}

Except for the @ sign and the use of HTML tags, the switch statement in this example could appear in any C# file. All the same rules apply as when working with C#, so you don't have to do anything weird except remember that @ sign and the fact that you can do something interesting with the HTML.

Implementing Loops

As you might expect, Razor implements loop processing using the same techniques that you use in C#. The difference is in how you process the data and the outcome of any tasks you perform. The following sections show how to create an array, so you have source data to process, and then how to process the data using a number of different techniques.

Creating an array

An array in Razor can take any form that you use in C#. Of course, you need to create it within an @ block or use an existing array of values. Here's an example of creating an array for use within the example:

@{
string[] Colors =
{ "Red", "Orange", "Yellow", "Green", "Blue", "Violet" };
}

As you can see, there is nothing weird here. The same techniques you use to create a C# array normally apply here as well.

Performing tasks a specific number of times using for

The Colors array created in the previous section provides a perfect way to test for loop processing in Razor. The following code uses the Colors array as a source and displays each of the colors in turn:

<h3>Colors</h3>
<ul class="text-left">
@for (var i = 0; i < Colors.Length; i++)
{
<li>Color @i is @Colors[i]</li>
}
</ul>

As with the previous examples, you need to use the @ sign before you create the for loop. In addition, this example shows how you might process a source array so that it appears correctly onscreen. Remember that you can use all the same techniques as you normally use with a for loop to process data in C#.

Processing an unknown number of times using foreach and while

The essential difference between a for loop and both foreach and while is that the former processes data a known number of times, while the latter process data an unknown number of times until they're finished. In many cases, the choice of looping mechanism comes down to style and preference. Some developers like one form and other developers like another form. Here is the same output provided in the previous example using a foreach statement.

<h3>Colors Using Foreach</h3>
@{
int counter = 0;
}
<ul class="text-left">
@foreach (string item in Colors)
{
<li>Color @counter is @item</li>
counter++;
}
</ul>

The example begins by declaring an int variable, counter, to keep track of the color number. It then uses the @foreach loop to process the Colors array. The differences you should notice in this version of the example are the technique used to produce the output and the fact that the example freely mixes HTML and C# code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.111.33