ASP.NET Core MVC Anchor Tag Helper

In today’s post in my series on the ASP.NET Core MVC Tag Helpers, I will explore the Anchor tag helper. This tag helper is used generate href attributes to link to a particular controller action or MVC route.

This tag helper is an alternative to using @Html.ActionLink or @Url.Action helper methods. For example, the following code in a Razor view:

@Html.ActionLink("Register", "Register", "Account")

<a href="@Url.Action("Register", "Account")">Register</a>

…would generate 2 identical anchor html tags.

<a href="/Account/Register">Register</a>
<a href="/Account/Register">Register</a>

Using the anchor tag helper, we can generate the same HTML as above by adding the asp-controller and asp-action attributes to an anchor tag as follows:

<a asp-controller="Account" 
asp-action="Register">Register</a>

In simple examples like the one above, there is very little difference between the tag helper approach and the @Url.Action approach. The advantage of tag helpers over the @Html.ActionLink approach is that we can add html attributes or content to the a tag and those will be merged with the generated output. Adding attributes to the a tag was particularly clumsy with the @Html.ActionLink.

Adding Route Parameters

In some cases, you might need to specify additional parameters for the controller action that you are binding to. You can specify values for these parameters by adding attributes with the asp-route- prefix. For example, you might need to specify the id of a product you are linking to, you would add a asp-route-id attribute as follows:

<a asp-controller="Product" 
asp-action="Display"
asp-route-id="@ViewBag.ProductId">

View Details</a>

…would generate the following html when ViewBag.Id = 1:

<a href="/Product/Display/1">View Details</a>

You can specify values for as many parameters as you need using attributes with the asp-route- prefix.

Named Routes

Another option is to specify the controller and action using a named route. For example, if your application had a route named login defined as follows in your MVC route configuration:

routes.MapRoute(
name: "login",
template: "login",
defaults: new { controller = "Account", action = "Login" });

then you can bind an anchor tag to that route as follows:

<a asp-route="login">Login</a>

Protocol, Host and Fragment

The anchor tag helper also has options for specifying the protocol, host and fragment for the generated URL. These are useful if you want to override the defaults to force https or link to a particular portion of a page. To do this using the @Html.ActionLink approach, you would need to use the overload that accepts all possible options:

@Html.ActionLink("Register", "Register", "Account",  "https", "aspecificdomain.com", "fragment", null, null)

Notice that you need to specify null for the last 2 parameters (route values and html attributes). This would generate the following HTML:

<a href="https://aspecificdomain.com/Account/Register#fragment">Register</a>

If all you wanted to do was specify https for the current domain, you would need to pass null to 4 parameters:

@Html.ActionLink("Register", "Register", "Account",  "https", null, null, null, null)

With the tag helper approach, you can use any combination of the asp-protocol, _asp-host _and asp-fragment attributes you want. This avoids messing around with method overloads that contain parameters you don’t care about in the current context. The result is a much cleaner syntax that, in my opinion, is easier for the reader to understand:

<a asp-controller="Account" 
asp-action="Register"
asp-protocol="https"
asp-host="asepecificdomain.com"
asp-fragment="fragment">Register</a>


<!--or with the protocol only -->
<a asp-controller="Account"
asp-action="Register"
asp-protocol="https">Register</a>

Conclusion

That wraps up the functionality provided by the anchor tag helper in ASP.NET Core MVC. In the next post in this series we will explore the Cache tag helper.

ASP.NET Core MVC Form Tag Helper

So for in my series covering ASP.NET Core MVC tag helpers, I have covered all the tag helpers that you would use to generate the contents of a form:

In this post, I will cover the Form tag helper that is used to bind a Form element to a particular MVC controller action or named route. This tag helper is an alternative to the following HTML helper method syntax:

@using (Html.BeginForm("ControllerName", "ActionName"))
{
//Form Contents Here
}

Binding to Controller Action

With the form tag helper, you can bind a form to a specific controller action by adding the asp-controller and asp-action tag helper attributes to a form element.

For example, you can bind a form to the Login action of the Account controller as follows:

<form asp-controller="Account" 
asp-action="Login">

//Your form elements here
</form>

Any elements that you add inside the form will be included in the generated HTML. The example above would generate the following HTML:

<form action="/Account/Login" method="post">

//Your form elements here

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8AFtmUdx-b5MkQvAyGYbjFmMGSMv0Fmk7gG4RqGXlkNV6yqKqj6fgqnOh4TLT6ZnWSaqtAbKkgpEB20lvfkc2iOKZKIqt3tJ4Jij8DjmatTrZo-DKVOLwwOzj3kB8VKpFwc0rQMjaJTTC_gVv5f0vAg">
</form>

The form method was defaulted to post. You can specify this manually in your markup if you want. Any HTML attributes you add to the form element will be included in the generated HTML. However, if you attempt to both manually set the action attribute AND the asp-controller / asp-action attributes, the form tag helper will raise an error.

Cannot override the ‘action’ attribute for <form>. A <form> with a specified ‘action’ must not have attributes starting with ‘asp-route-‘ or an ‘asp-action’ or ‘asp-controller’ attribute.

The form tag helper also automatically adds an Anti forgery token which will cover in more detail below.

Adding Parameters

In some cases, you might need to specify additional parameters for the controller action that you are binding to. You can specify values for these parameters by adding attributes with the asp-route- prefix. For example, it is common for the Login action to have a returnUrl parameter. This can be specified as follows:

<form asp-controller="Account" 
asp-action="Login"
asp-route-returnurl="@ViewBag.ReturnUrl"
method="post" >

</form>

…which would generate a form element with the action attribute containing the specified value for the returnurl parameter:

<form action="/Account/Login?returnurl=%2FHome%2FAbout" method="post">

//Your form elements here

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8AFtmUdx-b5MkQvAyGYbjFmMGSMv0Fmk7gG4RqGXlkNV6yqKqj6fgqnOh4TLT6ZnWSaqtAbKkgpEB20lvfkc2iOKZKIqt3tJ4Jij8DjmatTrZo-DKVOLwwOzj3kB8VKpFwc0rQMjaJTTC_gVv5f0vAg">
</form>

You can specify values for as many parameters as you need using attributes with the asp-route- prefix.

Binding to a Named Route

Another option is to specify the controller and action using a named route. For example, if I had a route named login defined as follows in my MVC route configuration:

routes.MapRoute(
name: "login",
template: "login",
defaults: new { controller = "Account", action = "Login" });

Then I could bind my form to the login route using the asp-route tag helper attribute:

<form asp-route="login" 
asp-route-returnurl="@ViewBag.ReturnUrl"
method="post" >

</form>

…which would generate the following HTML:

<form action="/login?returnurl=%2FHome%2FAbout" method="post">

//Your form elements here

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8AFtmUdx-b5MkQvAyGYbjFmMGSMv0Fmk7gG4RqGXlkNV6yqKqj6fgqnOh4TLT6ZnWSaqtAbKkgpEB20lvfkc2iOKZKIqt3tJ4Jij8DjmatTrZo-DKVOLwwOzj3kB8VKpFwc0rQMjaJTTC_gVv5f0vAg">
</form>

Anti-Forgery Token Option

As we saw earlier, the form tag helper attribute adds a hidden __RequestVerificationToken input. This hidden input contains an anti-forgery token that when used in combination with the [ValidateAntiForgeryToken] attribute on the controller action will help to protect your application against cross-site request forgery. You really should use this on all your forms but if for some reason you need to turn this off for a particular form, you can simply set the asp-anti-forgery token to false.

<form asp-controller="Account" 
asp-anti-forgery="false"
asp-action="Login">

//Your form elements here
</form>

Conclusion

That wraps up the functionality provided by the form tag helper in ASP.NET Core MVC. I think it provides a much cleaner syntax than the @using(Html.BeginForm()){…} syntax. What do you think? What will be your preferred syntax for forms in MVC?

ASP.NET Core MVC Select Tag Helper

In this post from my series exploring the ASP.NET Core MVC tag helpers, I will be covering the select tag helper.

The select tag helper is used to generated select and associated option elements for properties of your models. This is an alternative to the _Html.DropDownListFor _HTML helper method.

Select Tag Helper

The select tag helper is used by adding the asp-for attribute to a select element. For example consider a simple view model class containing a CountryCode property:

public class SimpleViewModel
{
public string CountryCode { get; set; }
}

You can bind a select element to the CountryCode property as follows:

<select asp-for="CountryCode"></select>

…which would generate the following HTML:

<select name="CountryCode" 
id="CountryCode">

</select>

Now this is not overly useful because it is an empty drowdown list. You will probably want to add some options to your select.

Adding options

There are a couple ways you can add options to the select. You can simply add options directly in the markup:

<select asp-for="CountryCode">
<option value="CA">Canada</option>
<option value="US">US</option>
<option value="--">Other</option>
</select>

In this case, the options specified in markup will be included in the generated HTML. The selected option will automatically be determined based on the value of the model property. For example, if the CountryCode property is set to ‘CA’ in the model, then the following HTML would be generated:

<select name="CountryCode" id="CountryCode">
<option selected="selected" value="CA">Canada</option>
<option value="US">US</option>
<option value="--">Other</option>
</select>

If the list of options is dynamically loaded from a data source, you can use the asp-items tag helper attribute. All you need to do is set the asp-items attribute to an IEnumerable. For example, if we had a list of countries available on the ViewBag, we could specify the select options as follows:

<select asp-for="CountryCode" 
asp-items="ViewBag.Countries">

</select>

This will generate a select with options for each of the SelectListItems in the Countries collection.

Multiple Select

The select tag helper will automatically generate a multi-select if the property specified in the asp-for attribute is an IEnumerable. For example, given the following model class:

public class SimpleViewModel
{
public IEnumerable<string> CountryCodes { get; set; }
}

Binding the asp-for attribute to the CountryCodes property as follows:

<select asp-for="CountryCodes" 
asp-items="ViewBag.Countries">

</select>

…would generate the following HTML:

<select name="CountryCodes" 
id="CountryCodes"
multiple="multiple">

<option selected="selected"
value="CA">Canada</option>

<option value="USA">United States</option>
<option value="--">Other</option>
</select>

Conclusion

That covers all the functionality provided by the select tag helper in ASP.NET Core MVC, which provides a clean syntax for generating select elements based on the values in your model. In the next post, I will cover the Form tag helper.

ASP.NET Core MVC Label Tag Helper

So far in this series on the ASP.NET Core MVC Tag Helpers, I have covered the Input Tag Helper and the Validation Tag Helper.

In today’s post, I will cover the Label Tag Helper.

The label tag helper is probably the most boring simplest of all the MVC tag helpers. Its purpose is simply to generate a label element for a property on your model. You use it by adding the asp-for attribute to a label element.

For example, given a model class with an Email property as follows:

public class SimpleViewModel
{
[Display(Name="Email Address")]
public string Email { get; set; }
}

we can bind the Email property of our model to a label as follows:

<label asp-for="Email"></label>

…which will generate the following HTML:

<label for="Email">Email Address</label>

Notice that the value of the generated for attribute matches the name of the property while the content of the label matches the Name from the Display attribute of the email property.

As with all the other tag helpers, other attributes are merged in with the generated HTML. Adding a class or any other attribute to the label tag will be included in the generated HTML. For example, adding 2 classes to the label as follows:

<label asp-for="Email" 
class="col-md-2 control-label">

</label>

…would generate this:

<label class="col-md-2 control-label" 
for="Email">

Email Address
</label>

This is an alternative to the Html.LabelFor HTML helper method.

That’s all there is to the label tag helper. You might be wondering why you would use this instead of simply typing the label element without the tag helper. I suppose the best reason would be that you automatically get the label value from the Display attribute. You also get strong typing with the model property. In theory, if rename refactoring should automatically get applied to the tag helper but this is not working in the current preview of ASP.NET Tooling for Visual Studio.

In the next post, I will explore the text area tag helper.

ASP.NET Core MVC TextArea Tag Helper

In this post from the ASP.NET Core MVC Tag Helper series I will be covering the textarea tag helper.

The textarea tag helper is very similar to the input tag helper but specifically targets the textarea element instead of the input element. The textarea tag helper is used by adding the asp-for tag helper attribute to a text area element.

Consider the following model class:

public class SimpleViewModel
{
    [Required]
    [MaxLength(5000)]
    public string Description { get; set; }
}

We can bind a textarea to the Description property as follows:

<textarea asp-for="Description"></textarea>

…which would generate the following HTML:

<textarea name="Description" id="Description" 
          data-val-required="The Description field is required." 
          data-val-maxlength-max="5000" 
          data-val-maxlength="The field Description must be a string or array type with a maximum length of '5000'." 
          data-val="true"></textarea>

The text area tag helper was able to generate name and id properties based on the name of the property specified in asp-for. It also generated _data-val _attributes to enable client side validation based on the Required and MaxLength attributes that were applied to the model property.

Note: This tag helper is an alternative to the Html.TextAreaFor HTML helper method.

As with the other tag helpers, any HTML attributes that you add to the textarea element will be merged with the generated attributes. For example, adding the rows and cols attributes as follows:

<textarea asp-for="Description" rows="5" cols="40"></textarea>

…would generate the following HTML:

<textarea name="Description" id="Description" 
     rows="5" cols="40" 
     data-val-required="The Description field is required." 
     data-val-maxlength-max="5000" 
     data-val-maxlength="The field Description must be a string or array type with a maximum length of '5000'." 
     data-val="true"></textarea>

That covers everything you need to know about the textarea tag helper. In the next post in the series I will cover the Select tag helper.

ASP.NET Core MVC Validation Tag Helpers Deep Dive

In the last post I explored the functionality of the ASP.NET Core MVC input tag helper. This included the ability for the input tag helper to add client side validation attributes to input elements based on data annotation attributes on your model classes. What I didn’t discuss is how we can display those validation messages. That’s where the validation tag helpers come in.

There are 2 validation tag helpers: the Validation Message tag helper and the Validation Summary tag helper.

Validation Message Tag Helper

The validation message tag helper is used to display a validation message for a specific property of your model class. To use it, simply add the asp-validation-for attribute to a span element.

<span asp-validation-for="Email"></span>

This will generate a span containing validation messages for the specified property. For example, if the email property is required and the user did not specify it, the email tag helper would generate the following HTML:

<span class="field-validation-error" 
data-valmsg-replace="true"
data-valmsg-for="Email">

The Email field is required.</span>

The tag helper found a model validation message for the Email property and placed it inside the span. It also added some data-val attributes so jQuery Validation knows where to place client side validation messages for the Email property.

Typically, we would place a validation message tag helper directly after the input tag helper for the same property. This allows for the validation message to be displayed in close proximity to the input that it applies to.

Note, this tag helper is an alternative to the @Html.ValidationMessageFor(m => m.Email) html helper method.

Merging HTML Attributes

Like all tag helpers, the validation message tag helper will merge the attributes it adds with any other attributes you add to the span. For example, we can add our own class=”text-danger” to the span:

<span asp-validation-for="Email"
class="text-danger"></span>

which would generate the following HTML:

<span class="text-danger field-validation-error" 
data-valmsg-replace="true"
data-valmsg-for="Email">

The Email field is required.</span>

 

Validation Summary Tag Helper

While the validation message tag helper is used to display validation messages that apply to a single property of your model, the validation summary tag helper is used to display validation messages that apply to your entire mode. You can optionally specify to include all property level validation messages in the summary or only display the messages that apply at the model level.

To use this tag helper, by add the asp-validation-summary attribute to a div element. The value of the attribute can be ValidationSummary.All, ValidationSummary.ModelOnly or ValidationSummary.None.

ValidationSummary.All will display both property and model level validations messages while ValidationSummary.ModelOnly will display only validation messages that apply to the model level. If ValidationSummary.None is specified, the tag helper will do nothing, which seems like a very strange thing to do. Instead of None, I would recommend you just not add the asp-validation-summary attribute in the first place.

<div asp-validation-summary="All"></div>

This would generate the following HTML when there are no validation messages to display:

<div class="validation-summary-valid" data-valmsg-summary="true">
<ul>
<li style="display: none;"></li>
</ul>
</div>

If the model has errors, it would generate something like this:

<div class="validation-summary-errors" data-valmsg-summary="true">
<ul>
<li>The Email field is required.</li>
<li>The Password field is required.</li>
</ul>
</div>

HTML attribute merging works too. You can add attributes to the div and they will be included in the generated HTML.

Note, this is an alternative to the @Html.ValidationSummary(true) html helper method.

Conclusion

That should cover everything you need to know about the validation tag helpers. They really are very simple to use.

In the next post, we will explore another simple tag helper: the Label tag helper.