POSTing and GETting with jQuery and MVC

By at December 28, 2010 14:30
Filed Under:

The jQuery library has an extensive set of AJAX functions which make it very easy to handle website functionality with all the Ajaxy goodness you’ve come to expect. However there are some gotcha’s when working with MVC and I thought I’d take some time to talk about them.

The first thing to remember is to decorate your Actions with the appropriate Http verbs, either [HttpPost] or [HttpGet]. By default MVC 2 only allows [HttpPost] requests when requesting a Json response. Phil Haack has a great article on this at http://haacked.com/archive/2009/06/25/json-hijacking.aspx.

In a project I am working on I want users to be able to add other users as friends, see if their friend is online, and if necessary, delete a friend. This jQuery function allows a user to add a friend:

   1: function acceptFriend(friendId) {
   2:     var url = "/Member/AcceptFriendRequest/";
   3:     var data = "friendId=" + friendId;
   4:     $.post(url, data,
   5:         function (json) {
   6:             if (json == "success") {
   7:                 //add the div to the My Friends section
   8:                 addNewFriendToList(friendId);
   9:             } else {
  10:  
  11:             }
  12:         }, 'json');
  13: }

You can see here that I am POSTing the data back to the server by defining the url, and any data that needs to be sent as well (lines 2 and 3). Then, depending on the response, add the friend to a friend list. I don’t use an ActionResult but instead use a JsonResult in the Member controller.

   1: [HttpPost]
   2: public JsonResult AcceptFriendRequest(int friendId)
   3: {
   4:   var status = "success";
   5:   try
   6:   {
   7:     var member = _appHelpers.GetAuthenticatedMember(User.Identity.Name);
   8:     var memberId = member.Id;
   9:     var memberFriend = (from mf in _db.MemberFriends
  10:                 where mf.MemberId.Equals(memberId) 
  11:                 && mf.FriendId.Equals(friendId)
  12:                 select mf).FirstOrDefault();
  13:      if(memberFriend != null)
  14:      {
  15:        memberFriend.Approved = true;
  16:        _db.SaveChanges();
  17:      }
  18:    }
  19:    catch(Exception ex)
  20:    {
  21:       status = "false";
  22:    }
  23:    return Json(status);
  24: }

One thing I have discovered that for POST actions you don’t need the [HttpPost] attribute, but I put it in there for readability. The code above is pretty straightforward and not difficult to understand. What caused me a few hours of head scratching was when I was trying to do a GET and find out if a user was online. Two things were standing in my way, and I realized I *needed* to use the [HttpGet] attribute, and override the JsonResult’s default of not allowing GETs. This jQuery checks to see if a user is online.

   1: $.ajax({
   2:   url: "/Member/UserIsOnline/" + friend, //friend is an (int) id defined earlier
   3:   type: "GET",
   4:   success: function (result) {
   5:       if (result == "true") {
   6:          $(friendElement).removeClass("friendOffline").addClass("friendOnline");
   7:       } else {
   8:          $(friendElement).removeClass("friendOnline").addClass("friendOffline");
   9:       }      
  10:    }
  11:  });

The JsonResult in the controller is decorated with [HttpGet]

   1: [HttpGet]
   2: public JsonResult UserIsOnline(int id)
   3: {
   4:  var member = _appHelpers.GetMemberById(id);
   5:  bool isOnline;
   6:  try
   7:  {
   8:    MembershipUserCollection users = Membership.GetAllUsers();
   9:    MembershipUser user = users[member.Email];
  10:    isOnline = user.IsOnline;
  11:  }
  12:  catch (Exception ex)
  13:  {
  14:    isOnline = false;
  15:  }
  16:  return Json(isOnline, JsonRequestBehavior.AllowGet);
  17: }

If you don’t add the JsonRequestBehavior.AllowGet parameter you will get the following error when attempting to run you code:

This request has been blocked because sensitive information could be disclosed to 
third
party web sites when this is used in a GET request. To allow GET requests,
set JsonRequestBehavior to
AllowGet.

Once you get these gotchas out of the way, you’re on your way.

Happy Programming from ComponentOne

James

Add comment




  Country flag
biuquote
  • Comment
  • Preview
Loading


About the author

James James is a five time and current Microsoft MVP in Client App Development, a Telerik Insider, a past Director on the INETA North America Board, a husband and dad, and has been developing software since the early days of Laser Discs and HyperCard stacks. As the Founder and President of the Inland Empire .NET User's Group, he has fondly watched it grow from a twice-a-month, early Saturday morning group of five in 2003, to a robust and rambunctious gathering of all types and sizes of .NET developers.

James loves to dig deep into the latest cutting edge technologies - sometimes with spectacular disasters - and spread the word about the latest and greatest bits, getting people excited about developing web sites and applications on the .NET platform, and using the best tools for the job. He tries to blog as often as he can, but usually gets distracted by EF, LINQ, MVC, ASP, SQL, XML, and most other types of acronyms. To keep calm James plays a mean Djembe and tries to practice his violin. You can follow him on twitter at @latringo.

And as usual, the comments, suggestions, writings and rants are my own, and really shouldn't reflect the opinions of my employer. That is, unless it really does.

James Twitter Feed

Recent Comments

Comment RSS

Month List