Although the convention proposed by the ASP.NET MVC framework help us to structure our applications and, in most cases, be more productive, occasionally also require us to enter repetitive code to comply with the proposed standard.
For example, in the case of controllers with actions that return the default view, we usually use a code like the following:
public class HomeController: Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Create()
{
return View();
}
public ActionResult Edit()
{
return View();
}
public ActionResult Delete()
{
return View();
}
}
It’s not terrible, but drivers with many actions of this type can be a bit heavy … can not we do something to improve this?
Automatic controllers
Looking at the driver code above, we see that the execution logic is very simple: every action returns the user implemented view as rightful convention. Obviously this is a widespread behavior may be playing with the extension mechanisms of the framework.
A very quick way to do it is to overwrite the method HandleUnknownAction() class Controller , described here some time ago , which allows us to process the requests made to non-existent shares in the controller.
Remember that when a request comes to a controller, running the method whose name matches the action invoked, in the absence of the framework call HandleUnknownAction() , allowing us to take control of the situation. In our case, we could introduce the logic in this method to return the user, automatically, a view whose name matches the action, following the standard naming convention.
To do this, simply create a base class called AutoController , and enter the following code to have the problem solved:
public class AutoController : Controller
{
protected override void HandleUnknownAction(string strActionName)
{
// Try to find a view with the name of the action ...
ViewEngineResult viewResult = ViewEngines.Engines.FindView
(this.ControllerContext, , null) ;
if (viewResult.View != null)
{
View(strActionName).ExecuteResult(ControllerContext);
return;
}
// If we have not found anything, we follow the
// Default behavior ...
base.HandleUnknownAction(strActionName);
}
Simple, no? All we do in the code is to use the library ViewEngines to seek a view whose name matches the action you are trying to run, returning it to the user if possible locate it.
If you can not find a view for the action invoked, will run the default treatment for this situation, which is nothing more than throwing an exception of type HttpException with error 404 (not found).
That’s it! From this point, all the driver classes that inherit from AutoController include this behavior, so it will be possible to avoid the implementation of methods whose sole mission is to return the default view as convention.
For example, the driver that we wrote at the beginning of this post might be as follows, much more compact:
public class HomeController: AutoController
{
}
But beware if that is not gold that glitters …
However, before using this technique we must be clear what it really means to not run into unpleasant surprises.
Each request received by the controller is not explicitly implemented will be processed with the operator introduced in HandleUnknowAction() without passing through any type of filter, or send any information in the ViewData .
For example, it would be possible to access the view directly, only know her name, which in some scenarios may be dangerous from the point of view of system security.
Obviously, the technique is also not valid at times when the sight expect to receive some form of driver information (like data view, or indication of use of a specific master page), or when the action must be decorated with a filter .
In these cases, these concrete actions should continue to be implemented explicitly in the controller, but the rest can continue to be processed automatically:
public class HomeController: AutoController
{
// GET /Home/Employers
// Only for registered users
[Authorize]
public ActionResult Employers()
{
return View();
}
// GET /Home/Salary
public ActionResult Salary()
{
var varAppServices = new AppServices();
return View(varAppServices.GetReferences());
}
// GET /Home/{ExamplePage}
// Default processing, returns the view {ExamplePage}
}
In summary, in this post we have studied a technique that allows us to create drivers capable of providing a default for all requests made to the same, saving the writing of actions that simply return the default view.
And although, like everything else, practice has limitations and dangers, its use can be interesting websites without major safety requirements, such as public information websites, whose drivers are mostly of the type described.



