ASP.NET Core Routing: Generating Outgoing URLs in Views

ASP.NET Core Routing: Generating Outgoing URLs in Views

The URL Routing is also used to create Outgoing URLs in Views. They address an important maintenance issue because the links are created automatically based on the routes in your application. So if you change the routes, the links created in the Views are automatically changed based on the new route and you don’t have to manually change the links one by one.

Did you checked my last tutorial on Attribute Routing, if not then make sure you do it.

Lets me show you how outgoing links are created.

First make sure you have only the below route in your application:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

Next add MVC View Imports Page inside the Views folder (right click on the Views folder and select Add ➤ New Item).

viewimports

The View Imports lets you import the namespaces need in your Views. Import the tag Helpers namespace because I will be creating links using them. The code is given below:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Next go to the Index View in your Home Controller and add the below line:

<a asp-action="Check">Outgoing URL</a>

Run your application and check the link formed. You can do this by right clicking on the browser and select ‘Inspect’ then click the link to check its HTML.

You will find the HTML of the Link formed is:

<a href="/Home/Check">Outgoing URL</a>

The reason why this link is formed is because I used ‘asp-action’ tag helper – asp-action=”Check” with the anchor tag. This tag helper tells MVC the name of the action method the URL in the HREF attribute should target. Here it is the ‘Check’ action method.

Note that MVC targets the particular action method of the same controller where the View is. I am placing the link in the Index action of the Home controller and so the outgoing link is targeting the Check action of the Home controller.
Creating Link targeting different Controller

If I want to target the Check Action of Customer Controller then I will have to also use the asp-controller tag helper in the anchor tag.

Add the below code in the Index action of the Home Controller to target the Check action of the Customer controller:

<a asp-controller="Customer" asp-action="Check">Check action of Customer Controller</a>

The link formed in this case will be:

<a href="/Customer/Check">Check action of Customer Controller</a>

Link Generation is Smart

Go to the Check action method of the Home Controller and create a link targeting the Index action method.

<a asp-action="Index">Go to Index</a>

You will find the link formed in this case contains just ‘/’ and not ‘Home/Index’, see below:

<a href="/">Go to Index</a>

The reason for this is that I have specified in the route that Home is the default Controller and Index it the default action. The MVC framework is smart enough and that’s why it does not Controller name and Action name on the Href attribute.

Generating links from Attribute Routes

Outgoing links can also be formed based on Attribute Routing. I had the Admin controller having attribute routing as given below:

[Route("News/[controller]/USA/[action]/{id:allowedgods?}")]
public class AdminController : Controller
{
    public string Index()
    {
        // Removed for clearity
    }
    
    // ....
}

In the ‘Index Action of Home’ Controller I can create a link to the ‘Index action of the Admin’ controller by putting the below code:

<a asp-controller="Admin" asp-action="Index">Index Action of Admin Controller</a>

This will form the link based on Attribute Routing, and is given below:

<a href="/News/Admin/USA/Index">Index Action of Admin Controller</a>

Outgoing Links Generation when Multiple Routes are present

You can have multiple routes present in your application. When you create an outgoing link the routing system process the routes in the order in which they are defined. It tries to match the route turn by turn. The match condition is based upon the 3 conditions:

1. Every URL segment has been provided with a value.

2. For the default-only variables, you must either not provide the value or provide the value that matches their default value.

Default-only variables are those that are not present in the URL but there default value is provided.

Consider the example, suppose my route which is shown below has

routes.MapRoute(
    name: "defaultonly",
    template: "{controller}/{action}",
    defaults: new { myCountry = "USA" }); 

The variable ‘myCountry’ is the default-only variable for this route. So for the Route system to make the match you should either not provide the value for variable ‘myCountry’ or provide value ‘USA’ for it (which is its default value).

3. The values of segment variables should satisfy the route constraint.

Example: Link Generation when Multiple Routes are present

Suppose you have 2 routes in your application which are given below:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "stock",
        template: "Stock/{action}",
        defaults: new { controller = "Home" });

    routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
});

Now go to your Index View of the Home Controller and add the below codes to generate links:

<a asp-action="Index">Link1</a>
<a asp-controller="Product">Link2</a>

You will find the first link is formed by the first route (stock) and the second link is formed by second route (default). This happens due to the 3 point of link generating which i mentioned previously.

The code for the links formed is given below:

<a href="/Stock/Index">Link1</a>
<a href="/Product">Link2</a>

Passing Values to Segments Variable other than Controller and Action

Till now you have seen how to make links targeting Controllers and Action methods. What If you want to pass values to other segment variable like ‘id’?

To do this make use of asp-route-* tag helper. Replace the * with the name of the segment variable like ‘id’.

Let’s create a link that passes a value for the ‘Id’ segment.

Create a new Product Controller and add an Index Action method as shown below:

using Microsoft.AspNetCore.Mvc;

namespace URLRouting.Controllers
{
    public class ProductController : Controller
    {
        public string Index(int id)
        {
            return "Id Value is: " + id;
        }
    }
} 

Now I need to link to this method from ‘Home’ Controller’s ‘Index’ View in such a manner that I pass a value of 100 for the ‘Id’ segment.

Just make use of the asp-route-* tag helper by adding the below code link to the ‘Home’ Controller’s ‘Index’ View:

<a asp-controller="Product" asp-action="Index" asp-route-id="100">Pass 100 to the id segment</a>

Now run your application and check the link formed, which will be –

<a href="/Product/Index/100">Pass 100 to the id segment</a>

Click the link and you will get the Id Value is: 100 displayed on the browser.

asp route tag helper

Passing Value to Query Sting

What if I pass value to a segment variable not described on the route? In this case the ASP.NET Core MVC will pass that value in Query String.

Let us discuss this feature.

My only route present is:

routes.MapRoute(
    name: "default",
    template: "{controller=Home}/{action=Index}/{id?}");

Change the Index Action of the Product Controller to include a string parameter as shown:

using Microsoft.AspNetCore.Mvc;
namespace URLRouting.Controllers
{
    public class ProductController : Controller
    {
        public string Index(int id, string name)
        {
            return "Id Value is: " + id + " Name value is: " + name;
        }
    }
}

Now in the ‘Index View of the Home Controller’ create a link to target the ‘Index Action of the Product Controller’ as shown below:

<a asp-controller="Product" asp-action="Index" asp-route-id="100" asp-route-name="Apple">Query String</a>

Note: I added asp-route-name=”Apple” to the anchor tag.

The link formed will be:

<a href="/Product/Index/100?name=Apple">Query String</a>

The link has a ‘name’ value passed as query string since there is no segment variable by the name of ‘name’ present in the route.

Click the link and the action method is able to fetch the value of ‘name’ segment. The below image shows this:

asp route query string

You can pass any number of query stings using the above method.

Generating Links from a Specific Route

You can also create the outgoing link from a specific route. Suppose there is a route in your application:

routes.MapRoute(
    name: "sales",
    template: "sales/{controller=Home}/{action=Index}");

Now to create a link based on it you use the tag helper asp-route=”name of the route”.

That means in your View you add the below code:

<a asp-route="sales">Sales</a>

The code of the link formed is:

<a href="/sales">Sales</a> 

The asp-route attribute can be used only when the asp-controller and asp-action attributes are absent. That means the route should have the default value for the Controller and Action.

Generation only URLs i.e. The HREF of Links

The Url.Action() method is used to generate the URL i.e. the HREF of Links.

In the Index Action of the Home Controller add the below link:

<p>URL: @Url.Action("List", "Product", new { id = 10 })</p>

You will find the generate URL as:

URL: /Product/List/10

The Url.Action() method take the following parameters:

1. Controller name.
2. Action name.
3. Name of other segment variable.

You can also use the Url.Action() method in the action method. See the below code that explains it.

String url = Url.Action("CustomVariable", "Home", new { id = 100 });

Adding URL Fragment (#)

The URL fragment denoted by a hash mark (#) is the optional last part of a URL for a document. It is typically used to identify a portion of that document. In HTML documents, the browser looks for an anchor tag with a name attribute matching the fragment.

For example, in the URL shown below the browser finds a matching tag in the Printing Support heading and scrolls the page to display that section:

<a name="/Product/List#Printing">Printing</a>

To create a URL Fragment we use asp-fragment=”fragment-name” tag helper. So the below code where I am creating a URL Fragment:

<a asp-controller="Product" asp-action="List" asp-fragment="Printing">URL Fragment</a>

The URL formed will be:

<a href="/Product/List#Printing">URL Fragment</a>

Append Trailing slash (/) to the URLs generated by the routing system

The RouteOptions object is also used to configure URL generation so that they contain a trailing slash (/). Go to the ConfigureServices method of the Startup class and add the options.AppendTrailingSlash = true; to where you configure the RouteOptions.

The code below explains it.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RouteOptions>(options =>
    {
        options.ConstraintMap.Add("allowedgods", typeof(OnlyGodsConstraint));
        options.AppendTrailingSlash = true;
    });
    services.AddMvc();
}

Run your application and the links generated on the View, you will find all of them ending with slash (/).

Example: the URL formed for the check action method will be – ‘http://localhost:58470/Home/Check/’.

The URLs should be in Lowercase

To make all URLs in Lowercase you can add the code – options.LowercaseUrls = true; inside where you are doing the RouteOptions configuration.

The below code explains it:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RouteOptions>(options =>
    {
        options.ConstraintMap.Add("allowedgods", typeof(OnlyGodsConstraint));
        options.AppendTrailingSlash = true;
	 options.LowercaseUrls = true;
    });
    services.AddMvc();
}

Now you will find the URL are all in lowercase.

Example: the URL formed for the check action method will be – ‘http://localhost:58470/home/check/’.

You can download the full codes of this tutorial from the below link:

Download

Conclusion

In this tutorial you learned to generate URLs from Routes in ASP.NET Core. Make sure to check other tutorials to.

Share this article -

yogihosting

ABOUT THE AUTHOR

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