makerofthings7
makerofthings7

Reputation: 61463

How should I design MVC to conditionally return JSON or pretty HTML?

I have data that will either be consumed by a human or a web service. The REST url is:

 http://host.com/movies/detail/1
 http://host.com/movies/detail/The Shawshank Redemption (1994)

What convention should I follow to conditionally return JSON or HTML? Should I add a parameter such as "?json" or should I look at the client headers,.. some variation of both?

If I do a variation of both, if a conflict is found which takes precedent?

Upvotes: 0

Views: 475

Answers (3)

Shyju
Shyju

Reputation: 218732

Check whether the Request is Ajax. You may use the Request.IsAjaxRequest() method which returns true/false.

public ActionResult details(string id)
{
  var movieViewModel=movieService.GetMovieDetails(id);
  If(Request.IsAjaxRequest())
  {
    // return Json now
    return Json(movieViewModel,JsonRequestBehavior.AllowGet);
  }
  // Not an ajax request, Let's return Normal View (HTML)
  return View(movieViewModel);
}

UNIT TESTING ASPECT : Request.IsAjaxRequest() is not unit test friendly! So if you are worried about unit tests, You can write your IsAjaxRequest property and put in your basecontroller class and use it.

public class BaseController : Controller
{
    protected bool IsAjaxRequest()
    {
        //Using this method instead of Request.IsAjaxRequest() because
       //IsAjaxRequest is static and not mockable ! (not unit test friendly)

        var isAjax = Request.Headers["X-Requested-With"];
        if (isAjax != null && isAjax.ToUpper() == "XMLHTTPREQUEST")
            return true;
        return false;
    }
}

Now inherit your controller from this BaseController.

public class HomeController : BaseController
{
    public ActionResult details(string id)
    {
      var movieViewModel=movieService.GetMovieDetails(id);
      If(IsAjaxRequest)
      {
        // return Json now
        return Json(movieViewModel,JsonRequestBehavior.AllowGet);
      }
      // Not an ajax request, Let's return Normal View (HTML)
      return View(movieViewModel);
    }

}

Upvotes: 3

juanjosegzl
juanjosegzl

Reputation: 64

I prefer using a parameter explicit in the URL because that way building REST petitions is easy for developers, self explanatory and with no surprises (do you have to guess default format? or see "difficult" to see HTTP headers). You decide:

  • if you have many options for formats you can use format=json
  • you can go with json parameter, but it is not pretty because you have to pair it with a value json=true, json=1. Besides you can set json=1&xml=1&html=1, harder to handle.
  • the twitter way is to emulate an extension such as call.json or call.xml (e.g. https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline)

I recommend don't tie together a kind of petition and a format. Let your API clients decide, ajax-json is commonly used, but not all develepers use it that way. Maybe I am writing a terminal application with no ajax, maybe I want to do a wget to your API and still get json.

Upvotes: 0

Damon Drake
Damon Drake

Reputation: 839

You could also use:

[HttpGet]
public ActionResult() {
    // Return HTML
}


[HttpPost]
public ActionResult() {
  // Assuming Ajax is of the type post
}

Just another solution if all your Ajax is using post.

Upvotes: 0

Related Questions