The .NET Team's Favorite Razor Features
Tags: dotnet, csharp, webdev
Published: 2021-09-01 18:27:28

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](https://twitter.com/shanselman)

I really like taghelpers like cache... It's so easy!

```csharp
@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>
```

[Docs: Cache taghelper](https://docs.microsoft.com/aspnet/core/mvc/views/tag-helpers/built-in/cache-tag-helper?view=aspnetcore-5.0&amp;WT.mc_id=dotnet-39599-jogallow)

## Implicit Razor expressions include async - [James Montemagno](https://twitter.com/jamesmontemagno)

This is a core Razor feature that allows you to call C# asynchronous code directly from your cshtml!

```csharp
<p>@await DoSomethingAsync("Hello", "from", "async")</p>
```

[Docs: Implicit Razor expressions](https://docs.microsoft.com/aspnet/core/mvc/views/razor?view=aspnetcore-5.0&amp;WT.mc_id=dotnet-39599-jogallow#implicit-razor-expressions)

## Custom Tag Helpers - [Damian Edwards](https://twitter.com/damianedwards)

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.

```csharp
[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:
```html
<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](https://taghelperpack.net/) repository.

{% github DamianEdwards/TagHelperPack %}

## Templated components - [Daniel Roth](https://twitter.com/danroth27)

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.

```csharp
<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; }
    }
}
```

[Docs: Templated components](https://docs.microsoft.com/aspnet/core/blazor/components/templated-components?view=aspnetcore-5.0&amp;WT.mc_id=dotnet-39599-jogallow)

## ViewComponentTagHelpers - [Taylor Mullen](https://twitter.com/ntaylormullen)

You can create a ViewComponent and have it return Content, Views or do any other complex logic:
```csharp
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:

```csharp
@addTagHelper *, WebApplication3000

<vc:foo />
```

[Docs: View Components](https://docs.microsoft.com/aspnet/core/mvc/views/view-components?view=aspnetcore-5.0&amp;WT.mc_id=dotnet-39599-jogallow)

## @inject - [Brady Gaster](https://twitter.com/bradygaster)

`@inject` is 🔥🔥🔥! I love that I can do that - it's crazy hawtsauce awesome.

Here's an example injecting configuration:
```csharp
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
   string myValue = Configuration["root:parent:child"];
   ...
}
```

You can also inject services:

```csharp
@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
](https://docs.microsoft.com/aspnet/core/mvc/views/dependency-injection?view=aspnetcore-5.0&amp;WT.mc_id=dotnet-39599-jogallow)

## Razor Class Libraries - [Jeff Fritz](https://twitter.com/csharpfritz)

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](https://github.com/FritzAndFriends/BlazorWebFormsComponents) project, which helps with migrating ASP.NET Web Forms project to Blazor.

Here's an example `Label` component, implemented as `Label.razor`:

```html
@inherits BaseWebFormsComponent

@if (Visible)
{
	<span id="@ID">@Text</span>
}
```

The logic is in `Label.razor.cs`:

```csharp
using BlazorWebFormsComponents.Interfaces;
using Microsoft.AspNetCore.Components;

namespace BlazorWebFormsComponents
{
	public partial class Label : BaseWebFormsComponent, ITextComponent
	{
		[Parameter]
		public string Text { get; set; }
	}
}
```

{% github FritzAndFriends/BlazorWebFormsComponents %}

## Use all the .NET Features - [David Pine](https://twitter.com/davidpine7)

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.

```csharp
@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 &mdash; 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:

```html
<div class="built-with"> 
.NET 6.0.0-preview.7.21377.19
</div>
```

## Explicit transitions - [Jon Galloway](https://twitter.com/jongalloway)

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.

```html
<script>
@for(int i = 0; i < 10; i++) 
{
    @:console.log(@i);
}
</script>
```

which will render:

```html
<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:

```html
@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>
}
```

{% codepen https://codepen.io/jongalloway-the-animator/pen/gORrzrz %}

[Docs: Dependency injection into views in ASP.NET Core
](https://docs.microsoft.com/aspnet/core/mvc/views/razor?view=aspnetcore-5.0&amp%3BWT.mc_id=dotnet-39599-jogallow#explicit-delimited-transition)

## 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](https://www.youtube.com/watch?v=5XWgEHcTe4k).

{% youtube 5XWgEHcTe4k %}

## What about you?
Got a favorite Razor feature you'd like to share? Drop it in the comments!