0

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?

2
  • 1
    You should really be using an Accepts header. Watch this, at around 6:00. Commented Nov 26, 2013 at 17:08
  • Is this a WebAPI? If so, just return an HttpResponseMessage. The framework will know what format to return based on the accept header. Commented Nov 26, 2013 at 22:29

3 Answers 3

3

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);
    }

}
Sign up to request clarification or add additional context in comments.

1 Comment

Should I also implement code that responds to the Accepts header?
0

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.