5 Ways Use Routing in ASP.NET Core

In software development, routing serves to map all incoming requests to handlers and generate the URLs used in responses. In ASP.NET Core, routing has been rewritten from the roots up. Previously, routing with MVC and Web API was very similar, but both were using different frameworks (and code) to do the same thing. An important difference was that Web API supported RESTful routes by default. For example, if a controller’s action method name started with Post, then invoking an HTTP Post would call that method by default.

Since Microsoft decided to rebuild and unify the routing framework, what applies now for MVC, applies also for Web API. Before we dig into how to build routing, however, let’s review why routing is so important for your application.

Why Routing?

SEO friendly

RESTfully configured routing facilitates the Search Engine Optimization (SEO) of your content. A site’s URL is one of the top criteria that impacts site ranking. By converting www.yourwebsite.com/articles/show/123 to www.yourwebsite.com/how-to-peel-potatoes you encourage search engines to rank it higher for keyphrases related to “how to peel potatoes.”

Also, when you have a URL that is more descriptive, it is easier for users to correctly anticipate the content, leading to increased time on page, which also impacts SEO and your overall page authority.

URLs do not need to map a file

Without routing, an incoming request would be mapped to a physical file. With routing we have full control of the request, allowing us to decide what action and controller we execute when a certain HTTP request comes in.

Long URLs and file extensions can be eliminated

Routing helps to shorten the URL in instances where many parameters and filters are in play. By eliminating the file extension, we can hide what kind of environment we are working in.

So, how do we take advantage of these benefits? Let’s look at five ways you can build routing in your ASP.NET Core application.

ASPHostPortal

1. Creating Default Routes

You can define the default route by convention in your project’s Startup class.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

With the above, we assure the essential configuration exists in our project for the standard MVC pattern of Controller + Action + ID (Optional) route. You can also declare the routing pattern like this:

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

(This is how we used to do routing in ASP.NET Core.)

2. Extending Default Routes

Once we have the default route configured, we might want to extend it by adding customized routes based on specific needs. For this, we can add configurations using the MapRoute() method.

app.UseMvc(routes =>
{
    //New Route
    routes.MapRoute(
       name: "about-route",
       template: "about",
       defaults: new { controller = "Home", action = "About" }
    );

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

We added an extra route which grants access to the About action on the Home controller with an /about route. Because the default pattern route is still present, we can also access the About page with the conventional /home/about route.

3. Using Attributes

You can also configure routes using attributes in your controller and actions.

[Route("[controller]")]
public class AnalyticsController : Controller
{
    [Route("Dashboard")]
    public IActionResult Index()
    {
        return View();
    }

    [Route("[action]")]
    public IActionResult Charts()
    {
        return View();
    }
}

In this sample we can access to the controller actions with the following routes:

  • /Analytics/Dashboard
  • /Analytics/Charts

You can see the two tokens [controller] and [action] indicate that we have to refer to the controller and action name that has been declared. In this case, “Analytics” is the name of the controller, and “Charts” the name of the action, therefore it the name of the route.

4. Building RESTful Routes

In order to declare a RESTful controller, we need to use the following route configuration:

[Route("api/[controller]")]
public class ValuesController : Controller
{
    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] {"hello", "world!"};
    }

    // POST api/values
    [HttpPost]
    public void PostCreate([FromBody] string value)
    {
    }
}

Here we are telling to our RESTful service to accept calls under the /api/values route. Note that we no longer use the Route attribute for actions. Instead we decorate it with HttpGetHttpPostHttpPutHttpDelete attributes.
Or, we can take a look at a different scenario:

// POST api/values/5
[HttpPost("{id}")]
public void PostUpdate(int id, [FromBody] string value)
{
}

Here we have the following routes for the controller Values

  • HTTP Post of /values route will invoke Post() action
  • HTTP Post of /values/PostName route will invoke Post([FromBody]string value) action

5. Using Constraints

We can restrict the type of value that we pass to actions using constraints. For example, if we expect an argument that is a number we have to restrict it to an integer type. Declare constraints in attributes using curly brackets {id:int}.

[HttpGet("{id:int}")]
public string GetById(int id)
{
    return "item " + id;
}

Here, we are telling the action GetByID to accept only an integer argument. Adding a question mark to the constraints {id:int?} indicates that the parameter is optional. Therefore with a question mark we can call /GetByID/123 or /GetByID without additional parameters. We can also define constraints in default routes declared in the Startup class this way:

routes.MapRoute(
    name: "getProductById",
    template: "Products/{id:int}",
    defaults: new { controller = "Products", action = "GetById" });

There are several available constraints like bool, datetime, decimal, min, max, regex, etc.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *