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.