In my continued effort to bring you some ASP.NET MVC Tutorials:
I mentioned earlier how I just finished Professional ASP.NET MVC 1.0 Framework. One of the tips in the book mentioned the concept of Implicit Action Results.
Typically when you see an action method on a controller class using the ASP.NET MVC Framework it is returning an ActionResult. Here is your typical out-of-the-box HomeController with Index and About Action Methods returning an ActionResult.
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewData["Message"] =
"Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
}
However, this doesn't have to be the case. I could create a simple Add Action Method on the controller that returns an Integer when adding two other Integers.
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
public int Add(int a, int b)
{
return a + b;
}
}
When I call into the action method, the ControllerActionInvoker notices that the return value is not an ActionResult ( and not void ) and returns the value as the content in a ContentResult.. To be more precise, it converts the value to a string and adds that to the content of a ContentResult. If the method returns void, the ControllerActionInvoker returns an EmptyResult. The beauty lies in the CreateActionResult Method of the ControllerActionInvoker that controls all of this:
protected virtual ActionResult CreateActionResult(
ControllerContext controllerContext, ActionDescriptor actionDescriptor,
object actionReturnValue)
{
if (actionReturnValue == null) {
return new EmptyResult();
}
ActionResult actionResult = (actionReturnValue as ActionResult) ??
new ContentResult { Content = Convert.ToString(actionReturnValue,
CultureInfo.InvariantCulture) };
return actionResult;
}
This method is virtual which means we can play with it. In fact, that is what I love to do ;) Let's create our own ControllerActionInvoker that overrides CreateActionResult and checks to see if this is a JSON request. If it is, let's wrap the response in a JsonResult:
public class CustomControllerActionInvoker : ControllerActionInvoker
{
protected override ActionResult CreateActionResult(ControllerContext controllerContext,
ActionDescriptor actionDescriptor, object actionReturnValue)
{
if (actionReturnValue == null)
return new EmptyResult();
var actionResult = actionReturnValue as ActionResult;
if (actionResult != null)
return actionResult;
// Return JSON
if (controllerContext.HttpContext.Request.ContentType.Contains("application/json"))
return new JsonResult {Data = actionReturnValue};
return new ContentResult { Content = Convert.ToString(actionReturnValue,
CultureInfo.InvariantCulture) };
}
}
Let's make this a bit more interesting in that we don't want to just return the sum, but possibly a return value that includes what you asked to have added:
public class AdditionProblem
{
public AdditionProblem(int firstNumber, int secondNumber)
{
FirstNumber = firstNumber;
SecondNumber = secondNumber;
}
public int FirstNumber { get; private set; }
public int SecondNumber { get; private set; }
public int Answer
{
get { return FirstNumber + SecondNumber; }
}
public override string ToString()
{
return string.Format("{0} + {1} = {2}",
FirstNumber, SecondNumber, Answer);
}
}
Let's rewrite the HomeController as:
[HandleError]
public class HomeController : Controller
{
public HomeController()
{
ActionInvoker =
new CustomControllerActionInvoker();
}
public object Add(int a, int b)
{
return new AdditionProblem(a, b);
}
}
The browser version just displays AdditionProblem.ToString():

However when I use Fiddler to send a JSON request I get JSON returned as you would expect:

Very neat! Another nice extensibility point in the ASP.NET MVC Framework that is sitting there for you to own!
So the question, my dear friends, is not “Why ASP.NET MVC?“ The question is “Why Webforms?“ I think Rob Conery says is best:
“WebForms is a lie. It’s abstraction wrapped in deception covered in lie sauce presented on a plate full of diversion and sleight of hand.“
Don't let all those armchair architects try to make you fit ASP.NET MVC into a neat, little niche need as if there is only one proper way to do web development and it is called ASP.NET Webforms. It's a lie :)
David Hayden