Thursday, December 29, 2022

ASP.NET Razor Pages made simple

Overview

This tutorial will show how easy it is to build web applications using .NET 7.0, C# and ASP.NET Razor Pages. You will develop a web app that calculates the future value on an investment based on a monthly contribution that you can make at a given interest rate for a number of years.

Source Code: https://github.com/medhatelmasry/SuperWeb

Companion Video: https://youtu.be/Zzu-WlkhnH8

Getting Started

To display different types of .NET applications that you can build, execute the following command in a terminal window on mac, Linux, or windows:

dotnet new --list

We want to create an ASP.NET Razor Pages application. Go to a working directory and run the following command from a terminal window to create an app in a folder named SuperWeb.

dotnet new razor -f net7.0 -o SuperWeb

OR

dotnet new webapp -f net7.0 -o SuperWeb

Change directory to the newly created folder with:

cd SuperWeb

To run the application in developer mode, run the following command:

dotnet watch

The web app will open in your default browser.

Open the web project in Visual Studio Code with the following command:

code .

Folders

Open Pages/Index.cshtml.cs in the editor and inspect its content.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace SuperWeb.Pages;

public class IndexModel : PageModel
{
    private readonly ILogger<IndexModel> _logger;

    public IndexModel(ILogger<IndexModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {

    }
}

Add the following line of code inside the OnGet() method:

ViewData["Name"] = "Queen Elizabeth";

The above code adds a string to a ViewData dictionary with key "Name". ViewData dictionaries can be passed from the Index.cdhtml.cs file to the Index.cshtml view file.

Open Pages/Index.cshtml in the editor.

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>

</div>

Add the following right before </div>:

<h2>@ViewData["Name"]</h2>

Our main page looks like this:

Create a new folder named Models. Inside the Models folder, add a file named FutureValue.cs with this code:

namespace SuperWeb.Models;

public class FutureValue
{
    public decimal MonthlyInvestment { get; set; }
    public decimal YearlyInterestRate { get; set; }
    public int Years { get; set; }
    public decimal CalculateFutureValue()
    {
        int months = Years * 12;
        decimal monthlyInterestRate =
        YearlyInterestRate / 12 / 100;
        decimal futureValue = 0;
        for (int i = 0; i < months; i++)
        {
            futureValue = (futureValue + MonthlyInvestment)
            * (1 + monthlyInterestRate);
        }
        return futureValue;
    }
}

Create a Razor page pair of files named FutureValue.cshtml and FutureValue.cshtml.cs in the Pages folder with:

dotnet new page --namespace SuperWeb.Pages --name FutureValue --output Pages

Add the below highlighted code to Pages/FutureValue.cshtml.cs:

using Microsoft.AspNetCore.Mvc.RazorPages;
using SuperWeb.Models;

namespace SuperWeb.Pages
{
    public class FutureValueModel : PageModel
    {
        public decimal MonthlyInvestment { get; set; }
        public decimal YearlyInterestRate { get; set; }
        public int Years { get; set; }

        public void OnGet()
        {
            ViewData["FV"] = 0;
        }

        public void OnPost(FutureValue model)
        {
            ViewData["FV"] = model.CalculateFutureValue();
        }
    }
}

Replace contents of Pages/FutureValue.cshtml with:

@page
@model SuperWeb.Pages.FutureValueModel
@{
    ViewData["Title"] = "Future Value Page";
}

<div>
    <form method="post">
        <div>
            <label asp-for="MonthlyInvestment">
                Monthly Investment:</label>
            <input asp-for="MonthlyInvestment" />
        </div>
        <div>
            <label asp-for="YearlyInterestRate">
                Yearly Interest Rate:</label>
            <input asp-for="YearlyInterestRate" />
        </div>
        <div>
            <label asp-for="Years">Number of Years:</label>
            <input asp-for="Years" />
        </div>
        <div>
            <label>Future Value:</label>
            <input value='@ViewBag.FV.ToString("C2")' readonly>
        </div>
        <button type="submit">Calculate</button>
        <a asp-action="Index">Clear</a>
    </form>
</div>

Start the app then point your browser to /FutureValue. You will see this page:

The above page calculates the future value of an investment that you make at a specific interest rate based on a monthly fixed contribution for a number of years. Try entering the following values, then click on Calculate:



The result should look like this:

Let us add a link to /FutureValue on the main menu of the application. Open Pages/Shared/_Layout.cshtml. Around line 26, replace (  <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a> ) with:

<a class="nav-link text-dark" asp-area="" asp-page="/FutureValue">Future Value</a>

You will see the Future Value link on the main menu.


Let us modify the “Future Value” form so that it looks more professional using bootstrap. Simply replace the <form> . . . . </form> HTML block in Pages/FutureValue.cshtml with:

<form method="post">
<div class="form-group">
<label asp-for="MonthlyInvestment" class="control-label"></label>
<input asp-for="MonthlyInvestment" class="form-control" />
</div>


<div class="form-group">
<label asp-for="YearlyInterestRate" class="control-label"></label>
<input asp-for="YearlyInterestRate" class="form-control" />
</div>

<div class="form-group">
<label asp-for="Years" class="control-label"></label>
<input asp-for="Years" class="form-control" />
</div>

<div class="form-group">
<label class="control-label">Future Value:</label>
<input value='@ViewBag.FV.ToString("C2")' readonly class="form-control">
</div>

<div class="form-group">
           <br />
<input type="submit" value="Calculate" class="btn btn-primary" />
<a asp-action="Index" class="btn btn-success">Clear</a>
</div>
</form>

If you run the application again, this is what you will see on the “Future Value” page:

Something is wrong. The labels (MonthlyInvestment, YearlyInterestRate, & Years) are not user friendly. They should be “Monthly Investment”, “Yearly Interest Rate” & “Number of years”. This is easily fixed using annotations on the model. Add the following highlighted annotations to Pages/FutureValue.cshtml.cs:

using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.RazorPages;
using SuperWeb.Models;

namespace SuperWeb.Pages
{
    public class FutureValueModel : PageModel
    {
        [Display(Name="Monthly Investment")]
        public decimal MonthlyInvestment { get; set; }
         
        [Display(Name="Yearly Interest Rate")]
        public decimal YearlyInterestRate { get; set; }

        [Display(Name="Number of years")]
        public int Years { get; set; }

        public void OnGet()
        {
            ViewData["FV"] = 0;
        }

        public void OnPost(FutureValue model)
        {
            ViewData["FV"] = model.CalculateFutureValue();
        }

    }
}

Note: You will need to import the System.ComponentModel.DataAnnotations namespace.

Now the page has user friendly labels that look like this:


There is much more you can do with razor pages and it is an easier alternative to ASP.NET MVC.

No comments:

Post a Comment