Net Core Tag Helpers

.Net core tag helpers

Hello everybody,

today I want to describe some .Net core tag helpers that you can use in order to create your web pages. There are plenty of already implemented tag helpers that can simplify your life as a developer.

Here is the list of already made:

  1. Anchor
  2. Cache
  3. Distributed
  4. Environment
  5. Form
  6. FormAction
  7. Img
  8. Input
  9. Label
  10. Link
  11. Option
  12. Script
  13. Select
  14. TextArea
  15. ValidationMessage
  16. ValidationSummary

It is not a complete list, but I suppose those 16 elements help you to grasp how wide it's functionality.

Anchor Tag Helper

Consider following declaration:

<a asp-controller='Presenter' asp-action='Presentation' asp-route-id=@Model.PresenterID>Presenter ID@Model.PresenterID</a>

List of Anchor tag helper attributes:

Anchor tag helper attribue Meaning
asp-controller Points to mvc controller ( for example Home or Account ). Word controller should be ommited
asp-action Points to view in controller ( for example index ). BTW, if you will write index, then only controller will be generated
asp-route Create routing between method of controller and name parameter of Rout Attribute. See image below table for visual explantion.
asp-route-{value}

Allows to generate urls with parameters. For example

<a asp-controller='Presenter' asp-action='Detail' asp-route-id=@Model.PresenterId>PresenterId@Model.PresenterId</a>
with following controller:

       [Route("Presenter/{id:string}")]
       public IActionResult Detail(string id)
       {

will generate following html:

<a href="Presenter/20">PresenterId: 20</a> 

In case if in model.PresenterId will be value 20

But if you change previous controller like this:

[Route("Presenter")]
       public IActionResult Detail(string id)
       {

then generated html will be like

<a href="Presenter?id=20">PresenterId: 20</a>

You can have as many as you want/need -{value} in your anchor tag

asp-all-route-data

Imagine situation that you don't know all your attributes for some reason. With asp-all-route-data you can genrate those attributes dynamically. Like this:

@{
    var prsenters = 
        new Dictionary<stringstring>
        {
            {"id""20"},
            {"presenter1""RobMartin"},
            {"presenter2""MartinFowler"}
        };
}
 
<a asp-route="presenters" asp-all-route-data="prsenters">Presenters</a>

and controller declared like this

       [Route("Presenter/{id:string}", Name = "presenters")]
       public IActionResult Presenters(string id)
       {

will give you following html output:

<a href="/presenters/20?presenter1=RobMarting&amp&amp;presenter2=MartinFowler"

asp-fragment Allows to define bookmarks in html which is possible to navigate.
asp-area

Allows you to add addional navigation.

asp-protocol Sets the protocol. Values can be http or https. If attribute asp-protocol is defined that full domain will be included in url. 

I recommend always to use asp-controller with asp-action in order not to confuse other developers and yourself later with questionmark what will be generated as outcome.

asp-route explanation. Imagine that you wrote following code in your cshtml view:

<a asp-route='presenterdetails'>Presentations</a>

According to traditional rules you may be puzzled how .Net core will be able to bind your anchor tag with contoller? Most probably somehow via asp-route. And you are correct. Take a look at following controller method declaration:

[Route("/Presenter/Presentations", Name = "presenterdetails")]
public IActionResult Presentations()
{
    return View();
}

.Net core will be able to bind your anchor to exact method via relationship asp-route <-> Name

or in the picture form:

Environment Tag Helper

Tag Environment allows you to render different content depending from environment at which you code works currently. For example you can use minimized jquery at production environment and not minimized jquery at development environment. 

Samples of declarations can be like this:

<environment names='Development'>
     <script
         src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.2.6/jquery.js">
     </script>
</environment>
 
<environment names='Staging,Production'>
      <script
           src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js">
      </script>
</environment>

and during development you will have option of deguggable js, while at production your pages will be reactive as well.

Cache Tag Helper

As it's name says Cache tag helper is intended for caching.

It can look like this:

<Cache expires-after="@TimeSpan.FromSeconds(15)">
    Cached time: @DateTime.Now
</Cache>

Presented declaration will create some html code that will remain unchanged 15 seconds. If you have some piece of code that generates some output inside of Cache tag, it will be preserved there for 15 seconds. 

Besides already mentioned attribute expires-after Cache tag helper has also the following attributes:

Attribute Functionality
expires-on This is time based expiration. Takes DateTime as parameter and expires according to passed DateTime
expires-after This is time based expiration. Takes TimeSpan. This is most commonly used attribute which preserves some content for some amount of time. 
expires-sliding This is time based expiration. Also takes as parameter TimeSpan, but each calling to cache will prolong caching for TimeSpan amount of time. If your site is heaviliy loaded then your content can last forever
vary-by-header This is so called list type expiration. Following code
<Cache vary-by-header="User-Agent,Accept-Language">
    Time cached : @DateTime.Now
</Cache>
will tell to .Net Core to refresh content if User-Agent, Accept-Language attribute of header was changed.
vary-by-query This is so called list type expiration. This is useful if you want to cache according to query parameters. Example of usage:
<Cache vary-by-query="param1,param2">
    Time cached according to param1, param2 : @DateTime.Now
</Cache>
vary-by-route This is so called list type expiration. This attribute looks at mvc attribute Route for caching. It means different routes can be cached.
vary-by-cookie This is so called list type expiration. Very similar to previous, just instead of passing route we pass cookie names here.
vary-by-user Takes bool parameter. One interesting feature of this attribute: no user is also treated as some abstract user and will be treated correspondingly.
vary-by Probably most  cunny attribute. For example this code
<Cache vary-by='@Model.Sum'>Time  : @DateTime.Now</Cache>
 allows to cache displayed time by some results of Sum calculation. vary-by allows to cache anything that is in our model.
vary-by-priority  It can have one of four enum values:
@CacheItemPriority.Low
@CacheItemPriority.High
@CacheItemPriority.Normal
@CacheItemPriority.NeverRemove
 
enabled Simply means enable or disable the cache. 

List type expiration means that you can pass list of comma separated values as parameter. 

Script tag helper

Besides features of standard html features script tag helper has additional features:

  1. Cache breaking. With attribute asp-append-version allow you to add ?v=someparame to your src attribute and will make your js not cached at all. Keep in mind though that this mechanism works for local files, not for remote urls. 
  2. Mask input for js file reading. Two attributes are asp-src-include and asp-src-exclude. They can look like this
    <script asp-src-include="/js/**/*.js" asp-src-exclude="/js/folder1/sub"  ></script>. Single start references single folder. Double start will include all folder and subfolders. That code will include all js files from folder js except those that are in folder folder1/sub.
  3. Load js if some cdn js is not available: asp-fallback-src

Ling tag helper

It is the same as script tag helper, but instead of src uses href. For example instead of asp-src-include it uses asp-href-include. 

Distributed Cache Tag Helper

It has the same parameters as cache helper but as name implies intended for providing distribution. Also it has the same attributes as Cache tag helper. The main difference is that Distributed cache helper allows injection of cache managers of your choice instead of built in InMemory cache helper. Among options can be redis or MS SQL cache. Another difference is that distributed cache requires attribute name to be set. It should be unique name in your whole web application. Consider some steps that you'll need in order to use SQL server cache:

  1. Add following nuget package: Microsoft.Extensions.Caching.SqlServer
  2. Configure Startup.cs 
  3. Create table that will be used for caching

Below goes example of configuration of adding distributed service cache of MS SQL server in Startup.cs file:

services.AddDistributedSqlServerCache(sqlServerCacheOptions =>
            {
                sqlServerCacheOptions.ConnectionString =
                    Configuration.GetConnectionString("DefaultConnection");
                sqlServerCacheOptions.SchemaName = "dbo";
                sqlServerCacheOptions.TableName = "SQLCache";
            });

You can use then following SQL for caching

CREATE TABLE[dbo].[SQLCache](    
  [Id]
  [nvarchar](449) NOT NULL,
  [Value][varbinary](max) NOT NULL,
  [ExpiresAtTime][datetimeoffset](7) NOT NULL,
  [SlidingExpirationInSeconds][bigint]
  NULL,   
  [AbsoluteExpiration]
  [datetimeoffset](7) NULL,   
  CONSTRAINT[pk_Id] PRIMARY KEY 
    CLUSTERED([Id] ASC) WITH(PAD_INDEX = OFF, 
	STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
	ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
  ON[PRIMARY]) ON[PRIMARY] TEXTIMAGE_ON[PRIMARY]

After those steps your code will get option of distributed caching. Among benefits of distributed cache I want to name one: persistance of cache during application restarts.

Image Tag Helper

Starting from old time it was an issue of caching of images. As usually it happend that if you uploaded some image, your users were able to see only old images, not a new ones. With .Net core it's pretty easy to solve. Just add 

asp-append-version="true" to your img tag like this:

<img src='~/images/a.jpg' asp-append-version="true" />

At my computer following html was generated:

<img asp-append-version="true" src="/Images/aligator.png?v=dlnlj_gStnFeM9RM9ADAm1fZA-MN_U1ile9VNQXWTaA">

You can consider as asp-append-version cache breaker. One word of warning. src attribute should point to local file. If it points to some url image then be ready for caching in any case.

1 Comment

  • Vijay said

    I have to thank you for the efforts you have put in penning this site.

    I really hope to check out the same high-grade blog posts from you in the
    future as well. In fact, your creative writing abilities has
    encouraged me to get my very own blog now ;)

Add a Comment
Comments are closed