What do you think about ASP.NET MVC as platform
for web service based applications? What about
JSON Web Services? Look at the following code:
public class OrderPorcessingController
{
public OrderPromotionResult PromoteOrder(string orderNumber)
{
var orders = new OrderRepository();
var order = orders.GetOrderByNumber(orderNumber);
order.PromoteOrder();
return new OrderPromotionResult
{
NewStatus = order.Status
};
}
}
public class OrderPromotionResult
{
public OrderStatus NewStatus { get; set; }
}
This code is actually ASP.NET MVC
Controller. The only notable difference is return
type. I return custom object. Not inherited from
ActionResult. For me looks good.
For example, I can test it without any
ASP.NET MVC bindings:
public void Should_change_status()
{
var processing = new OrderPorcessingController();
var result = processing.PromoteOrder("TestOrder");
Assert.Equals(OrderStatus.Promoted, result.NewStatus);
}
And at the end I have endpoint
/OrderPorcessing/PromoteOrder that accept
argument orderNumber and return
JSON.
Cool?
Implementation
Under the hood ASP.NET MVC, when action return
type not inherited from ActionResult wraps it's
ToString() to
ContentResult. Not so useful on the client side.
Of course, ASP.NET MVC has extensibility point
that exactly fits. Well, not exactly true. It has at least two
such points. Custom
ControllerActionInvoker
and no less custom
IActionFilter. In our production code we use custom
IActionFilter, however this post is about Custom
ControllerActionInvoker.
Custom ControllerActionInvoker
public class ServiceActionInvoker : ControllerActionInvoker
{
protected override ActionResult CreateActionResult(
ControllerContext controllerContext,
ActionDescriptor actionDescriptor,
object actionReturnValue)
{
ActionResult actionResult = (actionReturnValue as ActionResult) ??
new JsonResult { Data = actionReturnValue };
return actionResult ?? new EmptyResult();
}
}
Yes, it overrides CreateActionResult and wraps
result to the
JsonResult
instead of
ContentResult. That it.
To use this stuff you need to override
CreateActionInvoker.
protected override IActionInvoker CreateActionInvoker()
{
return new ServiceActionInvoker();
}
Enjoy!
P.S. Code with example could be found at GitHub.
For comments or feedback, write at x.com/chaliy.