Problem
How does ASP.NET Core MVC uses Razor engine to create dynamic views.
Solution
Configure conventional routing, as described in previous post, and add following controller:
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult AboutMe()
{
return View("Bio");
}
}
Add the two views (Index and Bio) in Views folder:
See Discussion section to go through Razor syntax.
Discussion
ASP.NET Core MVC middleware will find and execute the Razor template (.cshtml file) when the Controller returns ViewResult
. Razor templates use syntax that combine C# and HTML to produce the final HTML page.
Discovery Process
When ViewResult
executes it searches for the view, using the paths (in this sequence):
- Views/[Controller]/[Action].cshtml
- Views/Shared/[Action].cshtml
If template filename is different than action name then Controller can return ViewResult
and specify this:
public IActionResult AboutMe()
{
return View("Bio");
}
Razor Syntax
HTML is rendered unchanged:
Transition from HTML to C# is via @
symbol. C# code blocks are used with @ { // code }
:
C# expressions are used with @
symbol:
or @( // expression )
:
C# expressions are HTML encoded, below is HTML output and how browser renders it:
@Html.Raw
can be used to avoid encoding, below is HTML output and how browser renders it:
Control Structures
You could use various control structures in as a code block too, e.g. @if, @switch, @for, @foreach, @while, @do while
and @try
. Below are examples for these:
Directives
Razor views are converted into C# class (behind the scenes) that inherit from RazorPage
. Directives are ways to change the behaviour of these classes or the view engine. The commonly used directives are:
@using
Adds a using directive to generated C# class. Like C#, it’s used to import namespaces.
@model
Type specified will be used as T
in RazorPage
. Model is supplied from the controller when returning ViewResult
. This type can then be access via Model property of the page.
@inject
Used to inject services (registered in service container in Startup). You need to provide the service type and a name (to be used in the view). Dependency injection is views is useful when supplying strongly typed lookup data to views, which otherwise needs dynamic ViewData
or ViewBag
.
Below is an example of @using, @model
and @inject
directives:
Create a service:
public interface IGreeter
{
string Greet(string firstname, string surname);
}
public class Greeter : IGreeter
{
public string Greet(string firstname, string surname)
{
return $"Hello {firstname} {surname}";
}
}
Configure service in ASP.NET Core service container:
public void ConfigureServices(
IServiceCollection services)
{
services.AddScoped<IGreeter, Greeter>();
services.AddMvc();
}
Create a model:
public class AboutViewModel
{
public string Firstname { get; set; }
public string Surname { get; set; }
}
Return model from controller action:
public IActionResult AboutMe()
{
var model = new AboutViewModel
{
Firstname = "Tahir",
Surname = "Naushad"
};
return View("Bio", model);
}
Now you can use the model and service from the view:
@using Fiver.Mvc.Razor.Models.Home
@model AboutViewModel
@inject IGreeter GreeterService
@GreeterService.Greet(Model.Firstname, Model.Surname)
Source Code
GitHub: https://github.com/TahirNaushad/Fiver.Mvc.Razor