Built-In Tag Helpers in ASP.NET Core

Built-In Tag Helpers in ASP.NET Core

Built-In Tag Helpers are pre-built in the ASP.NET Core Framework and are used internally by the Razor. They perform common tasks like creating forms, showing validation messages, binding elements with Model, etc. In this section I am going to discuss about the Tag Helpers for Form, Input, Select, Label, Anchor, Text Area elements, CSS, JS and Cache.

This tutorial is a part of the series called Tag Helpers in ASP.NET Core. It contains 3 tutorials.

Tag Helper for the Form Element

Form Tag Helpers are used to target the correct Action method based on the application’s routing configuration.

The Built-in Tag Helpers for the Form Element that are used for generating the action attribute are:

Method Description
asp-controller Used for specifying the controller to target based on routing system.
If omitted then the controller of the current view is used.
asp-action Used for specifying the Action method to target based on the routing system.
If omitted then the action rendering the current view is used.
asp-route-* Used for specifying the additional segment value for the URL.
Eg asp-route-id is used to provide value for the ‘id’ segment.
asp-route Used for specifying the name of the route to target for generating action attribute
asp-area Used for specifying the name of the area to target.
asp-antiforgery Generates a hidden Request Verification Token to prevent cross-site request forgery. It is used with the [ValidateAntiForgeryToken] attribute in the HTTP Post action method.

It’s time to use these Form Tag Helpers in our application. So create a new view inside Views ➤ Home folder and name it Create. Add the below code to it:

@model Product
 
@{
    ViewData["Title"] = "Create";
}
 
<h2>Create</h2>
 
<form method="post" asp-controller="Home" asp-action="Create">
    <div class="form-group">
        <label for="Name">Name:</label>
        <input class="form-control" name="Name" />
    </div>
    <div class="form-group">
        <label for="Price">Price:</label>
        <input class="form-control" name="Price" />
    </div>
    <div class="form-group">
        <label for="Quantity">Quantity:</label>
        <input class="form-control" name="Quantity" />
    </div>
    <button type="submit" class="btn btn-primary">Add</button>
</form>

In the View I created a form tag. Notice the use of asp-controller="Home" and asp-action="Create" Tag Helpers to create the action attribute of the form.

The form has the method of type post so that means when the form will be submitted then the Create Action of type HttpPost will be invoked. So go to the Home Controller and add the 2 Create actions, one for HttpGet and the Other for HttpPost.

The Codes for these 2 Actions are shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using TagHelpers.Models;

namespace TagHelpers.Controllers
{
    public class HomeController : Controller
    {
        private IRepository repository;
        public HomeController(IRepository repo)
        {
            repository = repo;
        }

        public IActionResult Index()
        {
            return View(repository.Products);
        }

        public ViewResult Create()
        {
            return View();
        }

        [HttpPost]
        public IActionResult Create(Product product)
        {
            repository.AddProduct(product);
            return RedirectToAction("Index");
        }
    }
}
Remember to apply [HttpPost] attribute to the action of type Post. Actions without [HttpPost] attributes are of [HttpGet] type by default.

I have applied the HTML for attribute on the label elements. It specifies the element with the label it is bound to.

The Input elements have been given names – ‘Name’, ‘Price’ & ‘Quantity’. These are the names of the properties of the Model class called Product.cs. By giving them these names MVC will automatically bind the parameter of the HttpPost Create Action method (i.e. public IActionResult Create(City city)) with these values. This is the technique called Model Binding and it is very-very useful in creating highest quality codes.

Now run your application and go to the URL – https://localhost:44327/Home/Create (port may be different for you). Here you will see a form, so inspect the form element in your browser and you will see the action attribute created as /Home/Create.

This is shown by the Image given below:

form action tag helper

Next fill the create form and click the Add button (see the below image).

create form

You will find a new product is added to the repository with values you gave in the form. You will be redirected to the Index View which will show your recently added product (at the last) in the product list.

See the image below:

recently added product

Note : Since the form in the Create View is invoking none other than the same view (i.e. create view) it is currently in, therefore there is no need to apply asp-action and asp-controller tag helpers.

The below code works just great:

<form method="post">
....
</form>

asp-antiforgery Tag Helper

The asp-antiforgery Tag Helper Generates a hidden Request Verification Token to prevent cross-site request forgery (CSRF). When you use this attribute in your Form element, then ASP.NET Core MVC does two things:

  • 1. Adds a security token in a hidden input element to the form.
  • 2. Adds a cookie to the response.

The application will process the request only if it contains both the cookie and the hidden value from the form, which the malicious site cannot access, and hence CSRF is prevented.

To use this feature add the tag helper – asp-antiforgery="true" to the form element and add the attribute [ValidateAntiForgeryToken] in the Action method.

Go to the Create View and add the asp-antiforgery attribute to the form:

@model Product
 
@{
    ViewData["Title"] = "Create";
}
 
<h2>Create</h2>
 
<form method="post" asp-controller="Home" asp-action="Create" asp-antiforgery="true">
    // removed for clarity
</form>

Next add the [ValidateAntiForgeryToken] attribute on the HttpPost version of the Create Action method. I have highlighted this code line (see below code).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using TagHelpers.Models;

namespace TagHelpers.Controllers
{
    public class HomeController : Controller
    {
        private IRepository repository;
        public HomeController(IRepository repo)
        {
            repository = repo;
        }

        public IActionResult Index()
        {
            return View(repository.Products);
        }

        public ViewResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create(Product product)
        {
            repository.AddProduct(product);
            return RedirectToAction("Index");
        }
    }
}

Re-run your application and check the HTML code generated for the Create View. You will find the hidden input field created inside the form element and it contains the security token as shown by the image given below:

security token

Now in the Developer Tools window, go to the Application tab then click Cookies on the left panel. You will see the anti-forgery cookie created by Core MVC and it will be sent to the controller along with the response (see below image).

antiforgery cookie

In the Controller’s action the the attribute – [ValidateAntiForgeryToken] will automatically validate this cookie and security token.

Tag Helper for the Label Elements

The Label element has only one Tag Helper which is called asp-for. It is used to set the for attribute and the contents of the label element. To test this change the Create View to as shown in the highlighted code below:

@model Product
  
@{
    ViewData["Title"] = "Create";
}
  
<h2>Create</h2>
  
<form method="post" asp-controller="Home" asp-action="Create" asp-antiforgery="true">
    <div class="form-group">
        <label asp-for="Name"></label>
        <input class="form-control" name="Name" />
    </div>
    <div class="form-group">
        <label asp-for="Price"></label>
        <input class="form-control" name="Price" />
    </div>
    <div class="form-group">
        <label asp-for="Quantity"></label>
        <input class="form-control" name="Quantity" />
    </div>
    <button type="submit" class="btn btn-primary">Add</button>
</form>

Now when you inspect the page source html you will find see these label code are:

<label for="Name">Name</label>
<label for="Price">Price</label>
<label for="Quantity">Quantity</label>

The ‘asp-for’ Tag Helper does 2 things:

  • 1. Sets the for attribute of the label to the Model property’s name.
  • 2. Sets the content of the labels to the Name of the Model Property.

Tag Helper for “Input” Element

The Input element has a very useful Built-In Tag Helpers which is ‘asp-for’.

  • asp-for : This tag helper sets the name, Id, type and value attributes of the Input element.

Go to the Create View and use the asp-for tag helper for the input elements as shown in the below code.

@model Product
  
@{
    ViewData["Title"] = "Create";
}
  
<h2>Create</h2>
  
<form method="post" asp-controller="Home" asp-action="Create" asp-antiforgery="true">
    <div class="form-group">
        <label asp-for="Name"></label>
        <input class="form-control" asp-for="Name" />
    </div>
    <div class="form-group">
        <label asp-for="Price"></label>
        <input class="form-control" asp-for="Price" />
    </div>
    <div class="form-group">
        <label asp-for="Quantity"></label>
        <input class="form-control" asp-for="Quantity" />
    </div>
    <button type="submit" class="btn btn-primary">Add</button>
</form>

Run your application and request the URL – https://localhost:44327/Home/Create that initiates the Create View. Then check the HTML source of the Input elements. You will find the HTML of these Input elements now contains name, Id, type and Value attributes, as shown in the below code:

<input class="form-control" type="text" id="Name" name="Name" value>
<input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value>
<input class="form-control" type="number" data-val="true" data-val-required="The Quantity field is required." id="Quantity" name="Quantity" value>
The Price and the Quantity Input elements have additional attributes added to them. These are data-val, data-val-number, data-val-required. These are used for doing server side validation. I will teach you about them in the Model Validation Tutorial, so ignore them for the time being.

You will find the Name and Price inputs are of type text but the Quantity input has the type number. The reason is because the ASP.NET Core provides the type value to HTML controls based on the Model Property Types.

The below table tells about the how the different type values are given:

Model Type Type attribute for Input Element
byte, sbyte, int, uint, short, ushort, long, ulong Number
float, double, decimal text
string text
bool checkbox
DateTime datetime

Note : The asp-for Tag Helper when applied to a text area sets it’s id and name to that of the specified Model Property.

Tag Helper for the Select Element

There are 2 Built-In Tag Helpers for the Select element. These are given by this table below.

Name Description
asp-for Sets the id and name attribute of the Select element to the Model Property name.
asp-items Specifies the source of values for the option elements contained inside the Select element.

Let change the Create View’s quantity field from input to select as shown below:

<select class="form-control" asp-for="Quantity">
    <option disabled selected value="">Select Quantity</option>
    <option>50</option>
    <option>100</option>
    <option>150</option>
    <option>200</option>
</select>

Now check the HTML code created for the select element in the browser. You will see the that it contains the id and value attributes set as Quantity. See the below code:

<select class="form-control" data-val="true" data-val-required="The Quantity field is required." id="Quantity" name="Quantity">
    <option disabled="" selected="" value="">Select Quantity</option>
    <option>50</option>
    <option>100</option>
    <option>150</option>
    <option>200</option>
</select>

The MVC framework is very intelligent, when you bind the select control with the Model Value then you will see the select control’s value being automatically selected. To check this, add an Edit Action to the Home Controller. This action will return the last added record from the repository. The action method code is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using TagHelpers.Models;

namespace TagHelpers.Controllers
{
    public class HomeController : Controller
    {
        // removed for clarity

        public ViewResult Edit() => View("Create", repository.Products.Last());
    }
}

Now run your application and go to Create action’s URL which is https://localhost:44327/Home/Create. Here add a new record by giving name as ‘Pants’, Price as ‘88’ and Quantity as ‘150’.

See the below image:

adding new product

Now bind this last added product to the Edit View by going to it’s URL – https://localhost:44327/Home/Edit. You will clearly see the Quantity is selected as ‘150’ in the Select control.

Check the HTML source created for the select element and notice the selected attribute (selected="selected") applied to the option that contains 150th value, as shown by the below code:

<select class="form-control" data-val="true" data-val-required="The Quantity field is required." id="Quantity" name="Quantity">
    <option disabled="" selected="" value="">Select Quantity</option>
    <option>50</option>
    <option>100</option>
    <option selected="selected">150</option>
    <option>200</option>
</select>

This shows the intelligence of the Core MVC framework.

‘asp-items’ Tag Helper

The asp-items Tag Helper is used to specify the source of values for the option elements contained inside the Select Element. This helps to generate the option elements from the data source.

Change the Create View’s quantity select element’s code to:

<select class="form-control" asp-for="Quantity" asp-items="ViewBag.Quantity">
    <option disabled selected value="">Select a Country</option>
</select>

I specified a ViewBag.Quantity data source for the asp-items. Now I will also have to change the Create and Edit actions (HTTP GET Type). The changes are shown in the below given code in highlighted manner.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using TagHelpers.Models;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace TagHelpers.Controllers
{
    public class HomeController : Controller
    {
        private IRepository repository;
        public HomeController(IRepository repo)
        {
            repository = repo;
        }

        public IActionResult Index()
        {
            return View(repository.Products);
        }

        public ViewResult Create()
        {
            ViewBag.Quantity = new SelectList(repository.Products.Select(c => c.Quantity).Distinct());
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create(Product product)
        {
            repository.AddProduct(product);
            return RedirectToAction("Index");
        }

        public ViewResult Edit()
        {
            ViewBag.Quantity = new SelectList(repository.Products.Select(c => c.Quantity).Distinct());
            return View("Create", repository.Products.Last());
        }
    }
}

The ViewBag.Quantity property is set to a SelectList object that is populated with the unique values for the Quantity property in the repository.

The SelectList object resided inside the Microsoft.AspNetCore.Mvc.Rendering namespace.

Run your application and request the https://localhost:44327/Home/Create or https://localhost:44327/Home/Edit URLs and you will find that this time the option elements are created from the ViewBag.Quantity data source.

Tag Helpers for ‘Data Cache’

Data Cache is an in-memory cache for caching contents to speed up view rendering. You can keep a content of a View in cache element like:

<cache>
    Some Content
</cache>

Go to the _Layout.cshtml file and add the cache element for caching the current time in hours-minutes-seconds like shown below:

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link rel="stylesheet" asp-href-include="lib/bootstrap/css/bootstrap.min.css" />
</head>
<body>
    <div class="container-fluid">
        <div class="bg-info text-warning">
            <cache>
                Date Time: @DateTime.Now.ToString("HH:mm:ss")
            </cache>
        </div>
        @RenderBody()
    </div>
</body>
</html>

Now run your application and you will see the current time displayed on the top. Shown by the image given below:

caching current time

Now refresh the page and you will notice the time in hours, minutes and seconds remains the same. This is because the time is cached.

Some important Tag Helpers for the Cache Element are given below:

Name Description
expires-on Specify an absolute time in datetime value at which the cache expires.
expires-after Specifies the relative time in TimeSpan value at which the cache expires.
expires-sliding Sliding time is the period since the last usage.
So this tag helper specifies the sliding time in TimeSpan value at which cache expires.
vary-by-query Specifies the query string key that will be used to manage,
the different versions of the cache contents.
vary-by-cookie Specifies the cookie name that will be used to manage
the different versions of the cache contents.
vary-by Specifies a key to manage different versions of cache contents.
Using the ‘expires-after’ Tag Helper

Change the cache code in the _Layout.cshtml file to use the expires-after tag helper as shown below.

<cache expires-after="@TimeSpan.FromSeconds(20)">
    Date Time: @DateTime.Now.ToString("HH:mm:ss")
</cache>

This means now the cache expires after 20 seconds time.

Using the ‘expires-on’ Tag Helper

Now change the cache code in the _Layout.cshtml view to use the expires-on tag helper:

<cache expires-on="@DateTime.Parse("2050-01-01")">
    Date Time: @DateTime.Now.ToString("HH:mm:ss")
</cache>

This time the cache is cached until the year 2050.

Using the ‘expires-sliding’ Tag Helper

Now change the cache code in the _Layout.cshtml view to use sliding time expiry from expires-sliding tag helper.

<cache expires-sliding="@TimeSpan.FromSeconds(20)">
    Date Time: @DateTime.Now.ToString("HH:mm:ss")
</cache>

This will make the cache to expire in 20 second time from the last used time.

To test this thing you have to keep on reloading the page every 2 second, you will see the same time. Now wait for 20 seconds and then reload, and this time you will see the new time. This is because the cache expired in 20 seconds time from the last reload time.

Using the ‘vary-by’ Tag Helper

The vary-by Tag Helper is used to specify a key to manage different versions of cache contents.

Change the cache element on the _Layout.cshtml view as:

<cache expires-sliding="@TimeSpan.FromSeconds(10)" vary-by="@ViewContext.RouteData.Values["action"]">
    Date Time: @DateTime.Now.ToString("HH:mm:ss")
</cache>

This means the cache contents are made based on current action. Since there are 3 actions – Index, Edit and Create, so 3 versions of cache will be created (1 for each action method).

The expire-sliding tag helper set the sliding expiry time for these versions.

Tag Helpers for Anchor Tag

There are many Built-In Tag Helpers for the Anchor Tag which are used to create href attribute with target URL of the anchor tag, and it is based on the routing system.

The table below lists some of the important Tag Helpers for the Anchor tag:

Name Description
asp-controller Specifies the controller the URL will target.
asp-action Specifies the action the URL will target.
asp-area Specifies the area the URL will target.
asp-fragment Specifies the URL fragment (appearing after ‘#’ character)
as-route Specifies the route name the URL will target.
asp-route-* Specifies the additional value for the URL to target.
Example asp-route-id="10" provide the value 10 to the id segment of the route.

Go to the Index View and create an anchor link targeting the Create View as shown in the code below:

@model IEnumerable<Product>

<a asp-action="Create" class="btn btn-dark">Create</a>
<table class="table table-sm table-bordered">
    <thead class="bg-dark text-white">
        <tr>
            <th>Name</th>
            <th>Price</th>
            <th>Quantity</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var product in Model)
        {
            <tr>
                <td>@product.Name</td>
                <td>@product.Price</td>
                <td>@product.Quantity</td>
            </tr>
        }
    </tbody>
</table>

This will create a link:

<a class="btn btn-dark" href="/Home/Create">Create</a>

I did not provide the asp-controller tag helper because the Create View is in the same Controller which the URL targets.

If you use the asp-route-* tag helper in the Index view like:

<a asp-action="Create" asp-route-id="20" class="btn btn-dark">Create</a> 

Then the link formed will be:

<a class="btn btn-dark" href="/Home/Create/20">Create</a>

Tag Helpers for JavaScript Files

The Built-In Tag Helpers for the JavaScript files are used for managing inclusion and exclusion of JavaScript files from the Views.

Some important Tag Helpers for the JavaScript Files are:

Name Description
asp-src-include Specifies the JavaScript files to be included in the View.
asp-src-exclude Specifies the JavaScript files to be excluded from the View.
asp-append-version Specifies the query string to be applied to the JavaScript
file path whenever the contents of the file changes.
This is used for Cache Busting
asp-fallback-src-include Specifies the JavaScript file to include if there is some problem
with the Content Delivery Network.
asp-fallback-src-exclude Specifies the JavaScript file to exclude if there is some problem
with the Content Delivery Network.
asp-fallback-test Specifies a fragment of JavaScript that will be used to determine
whether the JavaScript is correctly loaded
from the Content Delivery Network.

You can also use set of wildcards to create pattern for matching files. These patterns can be used with asp-src-include, asp-src-exclude, asp-fallback-src-include and asp-fallback-src-exclude.

The Common patterns are:

Pattern Example Description
? JS/myscript?.js Matches single patter excluding ‘/’. The example on the left matches ‘JS/myscript1.js’, ‘JS/myscriptZ.js’, ‘JS/myscripts.js’, etc
* JS/*.js Matches any number of characters except ‘/’. The example given on the left side matches ‘JS/myscript.js’, ‘JS/validate.js’, ‘JS/js123.js’, etc
** JS/**.js Matches any number of characters including ‘/’. The example given on the left side matches ‘JS/Validate/myscript.js’, ‘JS/jQuery/validate.js’, ‘JS/js123.js’, etc

The patterns are very helpful because through them they make sure that the files are included in the View even if:

  • 1. The files are removed.
  • 2. The file names are changed.

Including JS files on the View

Let us include a bootstrap.js file in the _Layout.cshtml. The location of the file is wwwroot/lib/bootstrap/js/bootstrap.js.

The location is shown in the image below:

bootstrap js location

You will notice that there are 4 JS files in the same location:

1. bootstrap.js
2. bootstrap.bundle.js
3. bootstrap.bundle.min.js
4. bootstrap.min.js

Now go to the layout file and add the asp-src-include tag helper as shown in the code below:

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link rel="stylesheet" asp-href-include="lib/bootstrap/css/bootstrap.min.css" />
    <script asp-src-include="lib/bootstrap/**/*.js"></script>
</head>
<body>
    ...
</body>
</html>

Run your application and inspect the generated Html Source Code. You will find 4 JS files added to the HTML HEAD.

<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css" />
    <script src="/lib/bootstrap/js/bootstrap.js"></script>
    <script src="/lib/bootstrap/js/bootstrap.bundle.js"></script> 
    <script src="/lib/bootstrap/js/bootstrap.bundle.min.js"> 
    </script>
    <script src="/lib/bootstrap/js/bootstrap.min.js"></script>
</head>

The asp-src-include Tag helper generates the script tag for files that matches the pattern.

If you want only the bootstrap.bundle.js file included, then use the following matching pattern:

<script asp-src-include="/lib/bootstrap/**/*bundle.js"></script>

Excluding JS Files from the View

The asp-src-exclude tag helper is used to exclude files from the View.

Now this time use the below code in the layout View. This will remove all the ‘slim’, ‘min’ & ‘bundle’ JavaScript files from adding to the View.

<script asp-src-include="/lib/bootstrap/**/b*.js"
        asp-src-exclude="**.slim.*,**.min.*,**.bundle.*">
</script>

Run your application and check the HTML source code created. You will find only the bootstrap.js file added this time. See the below code:

<script src="/lib/bootstrap/js/bootstrap.js"></script>

Cache Busting feature from ‘asp-fragment’ Tag Helper

Images, CSS files and JavaScript files are cached on the browsers. So when you visit a page what requires these cached files, then the browser provides these files to the web page directly from it’s cache. This makes the page to load faster as these files are not request from the server.

Suppose you change the JavaScript file on your server but the browser will continue to provide this JavaScript file, to all the pages that requires it, from it’s cache. So new JavaScript changes are not reflected on the pages.

So how to cope up with this problem? There has to be some way to tell the browser to download the file from the server when you do changes to the file. Addressing this problem is called Cache Busting.

Cache Busting is done with asp-fragment Tag Helper. It adds a query string to the URL of the JS file that contains a checksum that acts as a version number. Now when you make any change to the JavaScript file then the checksum automatically changes and the browser knows that now it needs to download the latest JS file from the server and do it’s caching again.

Use the asp-fragment Tag Helper like shown below:

<script asp-src-include="/lib/bootstrap/**/b*.js"
        asp-src-exclude="**.slim.*,**.min.*,**.bundle.*"
        asp-append-version="true">
</script>

The HTML code now formed is:

<script src="/lib/bootstrap/js/bootstrap.js?v=82SVOjZ1qLdrq8VUmAisFapCSq1bpgavtXQaDGLPAAg"></script>

Including JavaScript files from Content Delivery Networks using Tag Helpers

Content Delivery Networks (CDN) contains a number of Data Servers distributed around the globe. All of these Data Servers have a saved copy of a website’s static files like images, CSS, JS. When a user opens the website in the browser then rather than requesting the static files from the website’s servers, it request them from the Data Server that is closest to the geographic location of the user.

This reduces the load time of the website and also saves the bandwidth. I advise you to use CDN even if your website is small.

jQuery is a very popular JavaScript library which can be loaded from the ASPNET CDN. The link is – http://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js

In the below highlighted code of the layout View I am loading jQuery from the ASPNET CDN. I have written a separate tutorial on jQuery CDN which contains detailed information.
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link rel="stylesheet" asp-href-include="lib/bootstrap/css/bootstrap.min.css" />
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
</head>
<body>
    ...
</body>
</html>

The asp-fallback-src-include, asp-fallback-src-exclude and asp-fallback-test Tag Helpers are made specifically to work with CDNs. Suppose, in case of some problem, the CDN fails to provide jQuery. In such a case you should load the jQuery from your website hosting server.

So update the layout’s code jQuery CDN code to this:

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link rel="stylesheet" asp-href-include="lib/bootstrap/css/bootstrap.min.css" />
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"
            asp-fallback-src-include="/lib/jquery/**/*.min.js"
            asp-fallback-src-exclude="**.slim.**"
            asp-fallback-test="window.jQuery">
    </script>
</head>
<body>
    ...
</body>
</html>

The src attribute of the script tag specifies the ASPNET CDN location to load jQuery.

The asp-fallback-src-include and asp-fallback-src-exclude Tag Helpers are used to select and exclude local jQuery files in case of CDN failure.

The asp-fallback-test Tag Helper defines a JavaScript code (here ‘window.jQuery’) that will be evaluated on the browser. If the code fails only then the asp-fallback-src-include and asp-fallback-src-exclude tag helpers will play their part.

Tag Helpers for CSS Files

The Built-In Tag Helpers for the CSS files are used for managing their inclusion and exclusion from the Views. These Tag Helpers are described below:

Name Description
asp-href-include Specifies the CSS files to be included in the View.
asp-href-exclude Specifies the CSS files to be excluded from the View.
asp-append-version Specifies the query string to be applied to the CSS file’s path
whenever the contents of the file changes. This is used for Cache Busting.
asp-fallback-href-include Specifies the CSS file to include if there is some problem
with the Content Delivery Network.
asp-fallback-href-exclude Specifies the CSS file to exclude if there is some problem
with the Content Delivery Network.
asp-fallback-href-test-class Specifies a CSS class that will be used to test the Content Delivery Network.
asp-fallback-href-test-property Specifies a CSS class property that will be used to test the Content Delivery Network.
asp-fallback-href-test-value Specifies a CSS class property value that will be used to
test the Content Delivery Network.

Including CSS files on the View

My application has many Bootstrap CSS files located under the wwwroot/lib/bootstrap/css folder as shown by the image given below:

bootstrap css files location

To include all the bootstrap CSS files from the asp-href-include Tag Helper change the code of the layout View as shown below.

<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link rel="stylesheet" asp-href-include="/lib/bootstrap/**/*min.css" />
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"
            asp-fallback-src-include="/lib/jquery/**/*.min.js"
            asp-fallback-src-exclude="**.slim.**"
            asp-fallback-test="window.jQuery">
    </script>
</head>
<body>
    ....
</body>
</html>

I have used the patters (** and *) for matching the files.

  • ** – for any number of characters including character ‘/’.
  • * – for any number of characters excluding character ‘/’.

This will add the files whose name end with .css. So the following 3 files are added.

<link rel="stylesheet" href="/lib/bootstrap/css/bootstrap-grid.min.css" />
<link rel="stylesheet" href="/lib/bootstrap/css/bootstrap-reboot.min.css" />
<link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css" />

Excluding CSS files on the View

The asp-href-exclude Tag Helper is used to exclude CSS files from View. Now use this tag helper to remove the reboot and grid CSS files.

See the code below:

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link rel="stylesheet" asp-href-include="/lib/bootstrap/**/*min.css"
          asp-href-exclude="**/*reboot*,**/*grid*" />
    <script asp-src-include="/lib/bootstrap/**/b*.js"
            asp-src-exclude="**.slim.*,**.min.*,**.bundle.*"
            asp-append-version="true">
    </script>
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"
            asp-fallback-src-include="/lib/jquery/**/*.min.js"
            asp-fallback-src-exclude="**.slim.**"
            asp-fallback-test="window.jQuery">
    </script>
</head>
<body>
    ...
</body>
</html>

Now this time only 1 CSS file is included:

<link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css" />

Including CSS files from Content Delivery Networks using Tag Helpers

You can also include CSS files from Content Delivery Networks using Tag Helpers. Let me show you how to add bootstrap.min.css file from MaxCDN.

Add the below highlighted code to the layout file:

<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"
          asp-fallback-href-include="/lib/bootstrap/**/*.min.css"
          asp-fallback-href-exclude="**/*reboot*,**/*grid*"
          asp-fallback-test-class="btn"
          asp-fallback-test-property="display"
          asp-fallback-test-value="inline-block"
          rel="stylesheet" />
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"
            asp-fallback-src-include="/lib/jquery/**/*.min.js"
            asp-fallback-src-exclude="**.slim.**"
            asp-fallback-test="window.jQuery">
    </script>
</head>
<body>
    ....
</body>
</html>

The href attribute specifies the CDN URL which in my case is the MaxCDN URL for bootstrap.min.cs file.

The asp-fallback-href-include and asp-fallback-href-exclude Tag Helpers are used to select the files from the website directory if the CDN is unavailable.

The next 3 Tag Helpers are used to test whether the bootstrap file correctly downloaded from the CDN or not. These tag helpers are:

  • 1. asp-fallback-test-class
  • 2. asp-fallback-test-property
  • 3. asp-fallback-test-value

They work by adding a meta element to the document that has been added to the class defined by the asp-fallback-test-class tag helper.

In my case the meta element added to the document will be:

<meta name="x-stylesheet-fallback-test" class="btn" />

Now the asp-fallback-test-property tag helper is used to specify a CSS property that is set by this CSS class (here ‘btn’), and the asp-fallback-test-value tag helper is used to specify the value that it will be set to.

These tag helper also add JavaScript to the view that tests the value of the CSS property on the meta element to figure out whether the CSS file has been loaded perfectly from the CDN or not. If the JavaScript test fails then the fallback CSS files are used instead.

You can download the source code using the below link:

Download

Conclusion

In this tutorial I have covered most of the part of Built-in Tag Helpers. In the next tutorial I will teach you how to make Custom Tag Helpers.

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "ASP.NET Core, jQuery, EF Core, SEO, jQuery, HTML" and more.