How to handle unknown actions in ASP.NET Core MVC 5

Handle unknown actions elegantly in ASP.NET 5 by creating routes that dynamically map to the views in your application.

How to handle unknown actions in ASP.NET Core MVC 5
CarlosCastilla / Getty Images

ASP.NET 5 is an open source web application development framework for building modern web applications. It is built on the .NET Core runtime and you can take advantage of it to build and run applications on Windows, Linux, and the Mac. ASP.NET Core MVC 5 is a lightweight, open source, highly testable framework built on top of the ASP.NET Core runtime and is available as part of ASP.NET 5.

When working in ASP.NET Core MVC, you might often need to handle actions that are not known at development time. This article talks about how you can handle unknown action methods in ASP.NET Core 5. The code examples are given in C#.

To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can download Visual Studio 2019 here. And you can download .NET 5.0 here.

Create an ASP.NET Core MVC 5 project in Visual Studio 2019

First off, let’s create an ASP.NET Core project in Visual Studio 2019. Following these steps should create a new ASP.NET Core 5 project in Visual Studio 2019.

  1. Launch the Visual Studio IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “ASP.NET Core Web App (Model-View-Controller)” from the list of templates displayed.
  4. Click Next.
  5. In the “Configure your new project” window, specify the name and location for the new project.
  6. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences.
  7. Click Next.
  8. In the “Additional Information” window shown next, select .NET 5.0 as the target framework from the drop-down list at the top. Leave the “Authentication Type” as None (default).
  9. Ensure that the check boxes “Enable Docker”, “Configure for HTTPS” and “Enable Razor runtime compilation” are unchecked as we won’t be using any of those features here.
  10. Ensure that Authentication is set to “None” as we won’t be using authentication either.
  11. Click Create.

A new ASP.NET Core MVC project will be created. We’ll use this project in the subsequent sections in this article.

Create a controller in ASP.NET Core MVC 5

If you look in the Solution Explorer window, you’ll see that a controller class named HomeController was created by default. Let’s create our own controller class, AuthorController, which we’ll use throughout this article. To do this, follow the steps outlined below:

  1. Right-click on the Controllers solution folder of your project in the Solution Explorer window. Select “Add -> Controller...”
  2. In the “Add New Scaffolded Item” window, select the “MVC Controller with read/write actions” project template and click Add.
  3. Specify a name for your new controller class (we’ll use AuthorController here) and click Add.

Replace the default code of the AuthorController with the following code:

   public class AuthorController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }
    }

In ASP.NET Core MVC, a controller is a class that is typically named with the suffix “Controller” and is used to define and logically group a collection of similar actions. Whenever you create a new controller, a default action method called Index is created automatically.

The default action method in ASP.NET Core MVC 5

Note that the name of the default action method, Index, is specified in the Configure method of the Startup class as shown in the code snippet given below.

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
       name: "default",
       pattern: "{controller=Home}/{action=Index}/{id?}");
});

Because the action name has been specified as Index in the preceding code snippet, you must have a file called Index.cshtml in the Views/Author folder of your project. You can now run the application and browse either of the following endpoints:

http://localhost:51913/Author
http://localhost:51913/Author/Index

You’ll observe that the Index page will be displayed in both cases.

The problem with unknown action methods

Let’s now understand the problem we’ll solve in this example. When working with ASP.NET Core MVC you will often need action methods that are not known at the time of development of the application.

Suppose you are building a searchable directory of publications, and you want users to be able to search by author name, or by book or article title. You would need to know the details of all the authors, books, and articles the directory will contain (i.e., author names, book titles, article titles, publication dates, and so on) in advance. How do you achieve that?

To accomplish this, you would need to have the corresponding views (i.e., Authors.cshtml, Books.cshtml, Articles.cshtml, etc.) in the Views folder as well as action methods that can be invoked using URLs such as the following:

/Author/Books 
/Author/Articles

Consider the following URL, which easily maps to the corresponding action method, namely the Index method of the AuthorController.

/Author/Index

However, if you try to browse either of the following endpoints, you’ll receive an error from the web browser because the corresponding action methods or views are not available.

/Author/Books
/Author/Articles

Use endpoint routing to handle unknown actions

We can solve this problem using routing — by creating a route that dynamically maps to an action that accepts a view name as a parameter and renders the view if a view with the specified name is found.

In the Startup.cs file, create a new route definition in the Configure method as shown in the code snippet given below.

endpoints.MapControllerRoute(
    name: "viewName",
    pattern: "{controller}/{*viewName}",
    defaults: new { action = "DisplayAnyView" });

The DisplayAnyView method looks like this:

public IActionResult DisplayAnyView(string viewName)
{
   return View(viewName);
}

The AuthorController now looks like this:

    public class AuthorController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }
        public IActionResult DisplayAnyView(string viewName)
        {
            return View(viewName);
        }
    }

When you execute the application now, you’ll observe that the break point is hit successfully as shown in the figure below.

aspnet core 5 unknown actions IDG

Use attribute routing to handle unknown actions

You can also solve the problem using attribute routing as shown in the code snippet given below.

[HttpGet("DisplayAnyView")]
public IActionResult DisplayAnyView(string viewName)
{
    return View(viewName);
}

Here is the complete code listing of the AuthorController class for your reference.

    [Route("[controller]")]
    public class AuthorController : Controller
    {
        [Route("[action]")]
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }
        [HttpGet("DisplayAnyView")]
        public IActionResult DisplayAnyView(string viewName)
        {
            return View(viewName);
        }
    }

Lastly, you should call the MapControllers method as shown in the code snippet given below to enable attribute-based routing.

app.UseEndpoints(endpoints =>
{
     endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}")
        endpoints.MapControllers();
});

An action method is a public and non-static method of a controller class that can handle incoming requests and is invoked based on an action. The ASP.NET Core MVC engine is adept at redirecting an incoming request to the corresponding action method. However, if there is no action method that matches the request, a runtime error will occur.

How to do more in ASP.NET Core:

Copyright © 2020 IDG Communications, Inc.