If you were reading the above code closely you might have
noticed a few changes with how Controller classes are by default implemented
using this new ASP.NET MVC source refresh drop.
With the ASP.NET MVC Preview 2 release the above
HomeController action methods would have instead been implemented like below:
Figure 6
The MVC feature team is experimenting with a few ideas in
this week's drop and are trying out some new ideas:
Action methods on Controllers now by default return an
"ActionResult" object (instead of void). This ActionResult
object indicates the result from an action (a view to render, a URL to redirect
to, another action/route to execute, etc).
The RenderView(), RedirectToAction(), and Redirect() helper
methods on the Controller base class now return typed ActionResult objects
(which you can further manipulate or return back from action methods).
The RenderView() helper method can now be called without
having to explicitly pass in the name of the view template to render.
When you omit the template name the RenderView() method will by default use the
name of the action method as the name of the view template to render. So
calling "RenderView()" with no parameters inside the
"About()" action method is now the same as explicitly writing
"RenderView('About')".
It is pretty easy to update existing Controller classes
built with Preview 2 to use this new pattern (just change void to ActionResult
and add a return statement in front of any RenderView or RedirectToAction
helper method calls).
Returning ActionResult Objects from Action Methods
So why change Controller action methods to return
ActionResult objects by default instead of returning void? A number of
other popular Web-MVC frameworks use the return object approach (including
Django, Tapestry and others), and we found for ASP.NET MVC that it brought a
few nice benefits:
It enables much cleaner and easier unit testing support for Controllers. You no longer have to mock out methods on the Response object or
ViewEngine objects in order to unit test the response behavior of action
methods. Instead, you can simply assert conditions using the ActionResult
object returned from calling the Action method within your unit test (see next
section below).
It can make Controller logic flow intentions a little
clearer and more explicit in scenarios where there might be two different
outcomes depending on some condition (for example: redirect if condition A is
true, otherwise render a view template it is false). This can make
non-trivial controller action method code easier to read and follow.
It enables some nice composition scenarios where a
FilterActionAttribute can take the result of an action method and
modify/transform it before executing it. For example: a
"Browse" action on a ProductCatalog controller might return an
RenderActionResult that indicates it wants to render a "List" view of
products. A FilterActionAttribute declaratively set on the controller
class could then have a chance to customize the specific "List" view
template rendered to be either List-html.aspx or List-xml.aspx depending on the
preferred MIME type of the client. Multiple FilterActionAttributes can
also optionally be chained together to flow the results from one to another.
It provides a nice extensibility mechanism for people
(including ourselves) to add additional features in the future. New
ActionResult types can be easily created by sub-classing the ActionResult base
class and overriding the "ExecuteResult" method. It would be
easy to create a "RenderFile()" helper method, for example, that a
developer writing an action could call to return a new "FileActionResult"
object.
It will enable some nice Asynchronous execution scenarios in
the future. Action methods will be able to return an AsyncActionResult
object which indicates that they are waiting on a network operation and want to
yield back the worker thread so that ASP.NET can use it to execute another
request until the network call completes. This will enable developers to
avoid blocking threads on a server, and support very efficient and scalable
code.
One of the goals with this interim preview is to give people
a chance to play around with this new approach and do real-world app-building
and learning with it.
We will also post an alternative Controller base class
sample that you can use if you still prefer the previous "void"
action return approach. We deliberately didn't include this alternative
Controller base class in this source refresh drop, though, because we want to
encourage folks to give the "ActionResult" return approach a try and
send us their app-building feedback on it.