ASP.NET MVC Tip #22 -- Return a View without Creating a Controller Action

In this tip, I demonstrate how you can eliminate controller methods that simply return views. I show you how to use the HandleUnknownAction method to handle every request against a controller automatically.

I saw Phil Haack use the following tip in a demo that he presented. I thought that it was such a great idea that I had to share it.

There is no good reason to write code unless there is a good reason to write code. I discover that I write a lot of controller actions that do nothing more than return a view. For example, consider the CustomerController in Listing 1.

Listing 1 – CustomerController.vb

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Web.Mvc
 
Namespace Tip22.Controllers
    Public Class CustomerController
        Inherits Controller
 
        Public Function Index() As ActionResult
            Return View()
        End Function
 
        Public Function Details() As ActionResult
            Return View()
        End Function
 
        Public Function Help() As ActionResult
            Return View()
        End Function
 
    End Class
End Namespace

Listing 1 – CustomerController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Tip22.Controllers
{
    public class CustomerController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
 
        public ActionResult Details()
        {
            return View();
        }
        public ActionResult Help()
        {
            return View();
        }
     
    }
}

This controller includes three actions that return three different views. Each of these actions contains a single line of code. In fact, each of these actions contains exactly the same line of code. This code reeks of needless work. How can we fix it?

The Controller class includes a method, named the HandleUnknownAction() method, that executes whenever you attempt to invoke an action on a controller that does not exist. The controller in Listing 2 takes advantage of the HandleUnknownAction() method to render views even when a corresponding controller method does not exist.

Listing 2 – HomeController.vb

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Web.Mvc
 
Namespace Tip22.Controllers
    <HandleError> _
    Public Class HomeController
        Inherits Controller
 
        Public Function Details() As ActionResult
            ViewData("message") = "Hello from controller action!"
            Return View()
        End Function
 
        Protected Overrides Sub HandleUnknownAction(ByVal actionName As String)
            Me.View(actionName).ExecuteResult(Me.ControllerContext)
        End Sub
 
    End Class
End Namespace
 

 

Listing 2 – HomeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Tip22.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Details()
        {
            ViewData["message"] = "Hello from controller action!";
            return View();
        }
 
        protected override void HandleUnknownAction(string actionName)
        {
            this.View(actionName).ExecuteResult(this.ControllerContext);
        }
 
    }
}

When you use the controller in Listing 2, you can call any action and the controller will attempt to return a view that corresponds to the action. You don’t need to explicitly code an action method for each view.

Notice that the controller includes a Details() action. When you need to pass ViewData, then you need to explicitly code the action method.

8 Comments

  • Thank you for your great tips!

  • As Eilon pointed out to me, you can accomplish the same thing using routing and a parameterized action method.

    Route: url="/show/{viewName}", defaults={controller="home", action=showview}

    public ActionResult ShowView(string viewName) {
    return View(viewName);
    }

    And now, you don't have to write action methods for each view in the views/home directory, you can just go to /show/viewname

  • @joshka - thanks for the feedback and for reading my blog. I have to publish excerpts because feedburner places a size limit on blog entries (feedburner stops broadcasting a blog when it gets too long). I'll look into a method for hiding/displaying different code versions. Thanks!

  • What if the client puts in a URL for a view that does not exist? I assume they get an error of some sort? What if we would like to display a "File (view) not found" page instead?

    Thanks.

  • I don't see why this would be good other then for DRY. If you go to a page that doesn't exist, you will encounter an exception (I would think, never tested it though) that the view doesn't exist. At this point, does MVC push the user to the error page or does an ugly exception page show up?

  • Great tip! I'll try it out. I just love a DRY tip :)

  • <a href= http://cry

  • <a href= http://stu

Comments have been disabled for this content.