Reputation: 8271
Rails has a nice idiom that makes it easy for you to have a single action method return properly formated data (json, xml, just the data) based on the format specified by the client (or else deduced from the request. It looks something like this ...
respond_to do |format|
format.html #edit.html.erb
format.json {render :text=> <your json here>), :layout=> false}
format.xml ...
end
What is the preferred way to do this in ASP.NET MVC? Ideally, I'd like the framework to work in the same way as Rails (e.g. be able to return the ViewData properly formatted for the format specified by the client or else deduced from the request itself).
Rails also allows you to create views that are specific to each type giving you the opportunity to essentially return the same data to all views and letting them handle formatting the data correctly (so you have a view that builds xml, another that builds json and yet another that builds html). Is this possible with ASP.NET MVC? In fact, this model seems to best keep with the goal of separating concerns imho as it lets the controllers return view-agnostic data whereas most approaches I see today (including the above line "format.json .... :layout => false") do the JSON conversion inside the controller and return that data directly to the client given a request for that format.
Anyhow ... suggestions, thoughts, recommendations?
Thanks
Upvotes: 0
Views: 617
Reputation: 6285
In ASP.NET MVC, controller actions generally return objects that derive from ActionResult
, which is then invoked by the runtime while generating the response stream.
Out-of-the-box you have several classes that derive from ActionResult
- ContentResult
for text results, ViewResult
for content from a view, JsonResult
for serializing an object hierarchy into JSON, RedirectResult
for redirecting, and so on.
Generally you pass in the model to the result and let it decide how to generate the result, but it doesn't have to be the same model - I can pass a different object to each result if necessary.
The concrete type of result returned by an action is not 'baked in' to the action's signature - you can easily pass in a format parameter to your action, and have it generate and return a different ActionResult accordingly:
public ActionResult ListProducts(string format)
{
List<Product> products = ProductService.GetAllProducts();
if (format == "JSON")
{
// eg., transform model for JSON consumption
List<JsonProduct> jsonProducts = ProductService.ToJSON(products);
return Json(jsonProducts);
}
else if (format == "XML")
{
return new XmlResult(products);
}
// default is to return HTML from view, which expects List<Product> for model
return View(products);
}
Note that the methods Json()
and View()
are built into the controller and are convenience methods for returning JsonResult
and ViewResult
respectively. XmlResult
is an example of a custom ActionResult
that takes an object, serializes it to XML, then returns the result as an XML stream.
The example is a little contrived, but it shows that the controller orchestrates all the work of selecting the result and constructing / transforming the model that is passed to that result. Controller actions should still be light-weight though so you offload the heavy tasks to services, such as loading the model from the business layer, or transforming objects in one model to objects in another model, such as for JSON consumption.
Upvotes: 2