Razor is a markup syntax for embedding .NET based code into webpages. It includes Razor markup, C#, and HTML. Files containing Razor generally have a .cshtml file extension. Razor is also found in Razor component files (.razor).
Razor is designed to be lightweight and unobtrusive, so you focus on your markup. However, there are a lot of hidden features that really come in handy! I asked some friends on the .NET team for some of their favorite Razor features, here's what they had to say.
Cache Tag Helper - Scott Hanselman
I really like taghelpers like cache... It's so easy!
@page
@model ArchivesModel
<cache expires-after="@TimeSpan.FromHours(4)">
@foreach (var show in Model.Shows)
{
<a href="@show.AsAwesomeUrl()" class="showCard">
<img data-src="@("https://images.hanselminutes.com/podcast/shows/"
+ show.Number + ".jpg")"
loading="lazy" class="lazyload"
src="/images/grey.gif" width="212" height="212"
alt="@show.Title" />
<span class="shownumber">@show.Number</span>
<div class="overlay title">
<!-- cant add padding to the wrapping div or the layout gets
messed up, title will be wrapped in a p tag
which will have the padding added to it -->
<p class="overlay-text">@show.Title</p>
</div>
</a>
}
</cache>
Implicit Razor expressions include async - James Montemagno
This is a core Razor feature that allows you to call C# asynchronous code directly from your cshtml!
<p>@await DoSomethingAsync("Hello", "from", "async")</p>
Docs: Implicit Razor expressions
Custom Tag Helpers - Damian Edwards
Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files. There are a lot of built-in ones, but it's also very easy to write your own.
Here's an example of an asp-if
Tag Helper that suppresses the output of the element if the supplied predicate equates to false.
[HtmlTargetElement("*", Attributes = "asp-if")]
public class IfTagHelper : TagHelper
{
/// <summary>
/// The predicate expression to test.
/// </summary>
[HtmlAttributeName("asp-if")]
public bool Predicate { get; set; }
public override void Process(TagHelperContext context,
TagHelperOutput output)
{
if (!Predicate)
{
output.SuppressOutput();
}
}
}
Here's how you'd use it:
<div asp-if="(DateTime.UtcNow.Minute % 2) == 0">
This paragraph will only render during <strong>even</strong> minutes.
</div>
<div asp-if="(DateTime.UtcNow.Minute % 2) == 1">
This paragraph will only render during <strong>odd</strong> minutes.
</div>
I've written a lot of sample tag helpers in this TagHelper Pack Samples repository.
DamianEdwards / TagHelperPack
A set of useful, and possibly opinionated, Tag Helpers for ASP.NET Core
A set of useful, and possibly opinionated, Tag Helpers for ASP.NET Core (all versions).
Included Tag Helpers & Examples
See the examples page at https://taghelperpack.net
Supports ASP.NET Core 6.0.x and 7.0.x. Also supports ASP.NET Core 2.1.x when running on .NET Framework 4.7.1 or higher.
Installing
-
Add a reference to the package from the cmd line:
MyGreatProject> dotnet add package TagHelperPack
-
Restore:
MyGreatProject> dotnet restore
-
Register the Tag Helpers in your application's
_ViewImports.cshtml
file:@addTagHelper *, TagHelperPack
-
Optional: Register optimizations in
ConfigureServices()
orProgram.cs
(ASP.NET Core 6+)services.AddTagHelperPack();
Templated components - Daniel Roth
Anything in a .razor
file is a work of art 😍
Templated components are pretty useful. They're components that accept one or more UI templates as parameters, which can then be used as part of the component's rendering logic. Templated components allow you to author higher-level components that are more reusable than what was possible before. For example, a list view component could allow the user to specify a template for rending items in the list, or a grid component could allow the user to specify templates for the grid header and for each row.
<h1>Pets</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
ViewComponentTagHelpers - Taylor Mullen
You can create a ViewComponent and have it return Content, Views or do any other complex logic:
using Microsoft.AspNetCore.Mvc;
namespace WebApplication3000
{
public class Foo: ViewComponent
{
public IViewComponentResult Invoke()
{
return Content("Hello, World!");
}
}
}
And then they instantly get transformed into TagHelpers that you can utilize in your views:
@addTagHelper *, WebApplication3000
<vc:foo />
@inject - Brady Gaster
@inject
is 🔥🔥🔥! I love that I can do that - it's crazy hawtsauce awesome.
Here's an example injecting configuration:
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
string myValue = Configuration["root:parent:child"];
...
}
You can also inject services:
@using System.Threading.Tasks
@using ViewInjectSample.Model
@using ViewInjectSample.Model.Services
@model IEnumerable<ToDoItem>
@inject StatisticsService StatsService
<!DOCTYPE html>
<html>
<head>
<title>To Do Items</title>
</head>
<body>
<div>
<h1>To Do Items</h1>
<ul>
<li>Total Items: @StatsService.GetCount()</li>
<li>Completed: @StatsService.GetCompletedCount()</li>
<li>Avg. Priority: @StatsService.GetAveragePriority()</li>
</ul>
<table>
<tr>
<th>Name</th>
<th>Priority</th>
<th>Is Done?</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>@item.Name</td>
<td>@item.Priority</td>
<td>@item.IsDone</td>
</tr>
}
</table>
</div>
</body>
</html>
Docs: Dependency injection into views in ASP.NET Core
Razor Class Libraries - Jeff Fritz
I like Razor Component Libraries. Just write a .razor file and it's a component that can be referenced. I used these a lot in my BlazorWebFormsComponents project, which helps with migrating ASP.NET Web Forms project to Blazor.
Here's an example Label
component, implemented as Label.razor
:
@inherits BaseWebFormsComponent
@if (Visible)
{
<span id="@ID">@Text</span>
}
The logic is in Label.razor.cs
:
using BlazorWebFormsComponents.Interfaces;
using Microsoft.AspNetCore.Components;
namespace BlazorWebFormsComponents
{
public partial class Label : BaseWebFormsComponent, ITextComponent
{
[Parameter]
public string Text { get; set; }
}
}
FritzAndFriends / BlazorWebFormsComponents
A collection of Blazor components that emulate the ASP.NET Web Forms controls of the same name
BlazorWebFormsComponents
A collection of Blazor components that emulate the web forms components of the same name
Approach + Considerations
We believe that Web Forms applications that have been well maintained and provide value should have a path forward to the new user-interface frameworks with minimal changes. This is not an application converted nor is it a patch that can be applied to your project that magically makes it work with ASP.NET Core. This repository contains a library and series of strategies that will allow you to re-use much of your markup, much of your business code and help shorten your application re-write process.
This is not for everyone, not everyone needs to migrate their application. They can continue being supported as Web Forms for a very long time (2029 EOL at the time of this writing) and the applications that are considered for migration…
Use all the .NET Features - David Pine
Here's a really useful Razor snippet. This is one of the things I love about Razor syntax, not only do I get to use my existing C# skills but I can use all the language features that make me a productive developer.
@using static System.Runtime.InteropServices.RuntimeInformation
<div class="built-with">
@FrameworkDescription
</div>
Your eyes are not fooling you, that is in fact a using static
declaration — meaning that all of the static members of the System.Runtime.InteropServices.RuntimeInformation
type are available without their type qualifier. I can seamlessly mesh HTML and C# together, using a powerful templating engine to create rich-content. This is a simple example, but there are many more. You’re limited by your imagination and the constructs surrounding HTML and C# semantics. When this is rendered as HTML, you’d end up with a <div>
element containing the .NET framework description. I love seeing the runtime version in my .NET apps 💜.
Resulting HTML:
<div class="built-with">
.NET 6.0.0-preview.7.21377.19
</div>
Explicit transitions - Jon Galloway
In most cases, Razor implicitly transitions between C# and HTML without you needing to think about it. It's occasionally useful to explicitly call out a block as HTML text inline in C# code. You can do that with an explicit transition. For example, this can be useful if you're writing out JavaScript or CSS from within a C# code block.
You can use the <text></text>
tag structure to delimit a block, and you can use @:
for a single line.
<script>
@for(int i = 0; i < 10; i++)
{
@:console.log(@i);
}
</script>
which will render:
<script>
console.log(0);
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
console.log(6);
console.log(7);
console.log(8);
console.log(9);
</script>
This is handy for things like rendering a chart with data populated on the server, like this:
@section Scripts {
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script>
window.onload = function () {
var dataPoints = [];
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
data: [
{
dataPoints: dataPoints
}
]
});
@{Random rand = new Random();}
@for(int i = 0; i < 10; i++)
{
@:dataPoints.push({ x: @i, y: @rand.Next(0, 100) });
}
chart.render();
};
</script>
}
Docs: Dependency injection into views in ASP.NET Core
Learn more about Razor and Razor Pages
Want to learn more about Razor and Razor Pages? Check out this 2 hour intro: Let's Learn .NET: Razor Pages.
What about you?
Got a favorite Razor feature you'd like to share? Drop it in the comments!
Top comments (6)
TIL
@:
syntax - thanks, Jon!I have recently started a website, the info you provide on this site has helped me greatly. Thank you for all of your time & work.
white magic spell for love
I have a start a blogging and program learning, very nice information and easy,
thanks for sharing
and also read my blog-
Backlink Kya hai
What is SEO in Hindi
Very cool and very useful!
Fantastic list. Glad to see that many of these are not Blazor specific.
I really really wish Templated Components worked for View Components 😭
Nice tips, thank you