With the advent of ASP.NET Core 2.0, Microsoft released a new way to build web apps called Razor Pages. It has some unique differences compared to the Model View Controller version of ASP.NET.

In this article, we will discuss:

  • The Razor Pages application project template
  • The structure of a Razor Pages project
  • Razor Page vs. MVC view
  • Controllers vs. page model
  • ASP.NET MVC routing & handlers
  • Model binding

Razor Pages Application Project Template

Example

The Razor Pages application has Web Application, a separate project template. Note that the MVC version is named Web Application (Model-View-Controller). This Razor Pages project template creates an ASP.NET Core project with a structure specific to Razor Pages. Although we have a separate template for Razor pages, it is possible to use within an MVC application. We simply need to add a Pages folder and begin adding Razor pages to it.

The Structure of a Razor Pages Project

This page-based application does not have the structure of an ASP.NET MVC application where you will find Model, View, and Controller folders. A Razor Pages application has a simpler folder structure; all pages reside under a Pages folder.

Razor Pages Project Structure

This structure provides an advantage, as project files can be organized according to functionality. For example, Dashboard view and its related code can reside in the same Dashboard folder making it easy to find and work with – no need to move between Controller and View folders. However, the same can be achieved in MVC using Areas.

Example

Razor Page vs. MVC View

A Razor page has an @page directive at the top and is similar to a Razor view with a .cshtml extension. This directive means that the page handles requests directly compared to MVC where the controller handles the request. You may create more subfolders under Pages folder to organize the structure.

MVC View:

@{
    ViewData["Title"] = "Home Page";
}

Razor Page View:

@page
<p>”Home Page”</p>

Controllers vs. Page Model

Controllers in MVC applications have Actions defined for user interactions.

MVC Controller:

public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }

In contrast, Razor pages have a Page model. These page models can be defined in the Razor page itself using the @model directive. Actions can be defined here using handlers.

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}
@function
{
    Public class IndexModel : PageModel
{
}
}

Alternatively, it can also be defined in separate code files for separation of concern and testability. When defining the PageModel separately in C#, the class must inherit from PageModel:

public class IndexModel : PageModel
    {
        public void OnGet()
        {
        //process logic
        }
    }

Routing & Handlers

In the ASP.NET MVC application, a combination of the controller and action names are used for routing. It can also have attributes to define routes with http verb and parameters.

A Typical MVC Routing:

public class CategoryController : Controller
{
            [HttpGet]
            public IActionResult Index()
                {
                    return View();
               }
}

In Razor Pages, routing is folder based and matches page location under /Page hierarchy. The associations of URL paths to pages are determined by the page's location in the file system. The following table shows a Razor Page path and the matching URL:

File name and path matching URL
/Pages/Index.cshtml / or /Index
/Pages/Dashboard/Index.cshtml /Dashboard/Index
/Pages/Reports/Index.cshtml /Reports or /Reports/Index

HTTP verbs are supported through handlers using OnVerb, like OnGet and OnPost. Route parameters can be added to the @page directive. The following example shows a OnPost handler:

Razor Page Handler:

public ActionResult OnPostSalesData
        {
            var model = Sale.GetData(100);
            return Json(model);
        }

Model Binding

Razor Pages has a BindProperty attribute that helps in model binding. Any property that is available to the view should have the BindProperty attribute set.

private CustomerOrder _customerOrder= new CustomerOrder { ID = 101, OrderTime = DateTime.Now, Product = "PlayStation 4" };
        [BindProperty]
        public CustomerOrder CustomerOrder
        {
            get { return _customerOrder; }
            set { _customerOrder = value; }
        }

Now, CustomerOrder is available in View and can be used like so:

View Code using Binding Property:

<form method="post">
        <div asp-validation-summary="All">
        </div>
        <div>
            <label asp-for="CustomerOrder.Price"></label>
            <c1-input-number for="CustomerOrder.Price"></c1-input-number>
            <span asp-validation-for="CustomerOrder.Price"></span>
        </div>

</form>

ASP.NET MVC and RazorPages: Basic Differences

RazorPages may look like webforms, but it incorporates all the good things of MVC like loose coupling and testability, It does not have view states, It also features out-of-the-box support for AntiForgeryToken.

Razor Pages are useful when the application needs to perform page-focused operations, like a CRUD operation or displaying reports from a hosted service. Architecturally, it is easier to create MVVM applications using the support for the Page-based model binding property.

ComponentOne Studio for MVC offers controls like grids, charts, input, navigation, and analysis for advanced data management and visualization, along with Visual Studio tools like project templates, scaffolders, wizards, client side TypeScript, and JavaScript Intellisense to quickly get you started and make it easy to write code.

View the controls in action inside Razor Pages here.

Happy coding!

Check out the latest version of ComponentOne today!

Download the latest version of ComponentOne Studio Enterprise

Download Now!