Interacting with ASP.NET Web API from the client!
7/18/2012If any of your have been paying attention you will notice that I have been all about Web API lately. It has been quite a struggle however because I am very weak in the areas on jQuery/javascript as well as understanding all the inner workings of http. A breakthrough has been made however! I have a demo of the super ghetto and not quote really working perfectly site here. Before I go any further, I will give the credit of this where credit is due. Thank you to pluralsight and Jon Flanders for the course. Walking through the first couple of modules really helped me get a grasp, though I did have to do some discovery to get mine to work.
To the code!
I am using Visual Studio 2012 RC with the latest patch as of the date of publishing this. I did a File > New Project, selected MVC4 (.NET v4.0) and chose the default internet application. Not going to go into the MVC structure here, email me, or look at my Custom MVC Blog posts in the archives if interested.
The first thing I did was clean up my HomeController:
public class HomeController : Controller { public ActionResult Index() { return View(); } public ActionResult Task(int id) { return View(id); } public ActionResult Create() { return View(); } }
I also adjusted the layout page navigation bar to match this stuff I changed. Next I needed some data to interact with so in the models folder I add a Model.cs file and a ModelInitializer.cs file. The first to define the model, the second to load it up with some dummy data. Here they are:
Model (Nevermind the name):
public class Onus { public int id { get; set; } public string name { get; set; } public string content { get; set; } public bool hasLocation { get; set; } }
And here is the Initializer:
public static ListInitOni() { var ret = new List (); ret.Add(new TaskIt.Models.TaskItModels.Onus { id = 0, name = "Get Milk", content = "Get 2 gallons of milk from the store", hasLocation = true}); ret.Add(new TaskIt.Models.TaskItModels.Onus { id = 1, name = "Read Pride and Prejudive", content = "Try to finish it sooner than later", hasLocation = false }); ret.Add(new TaskIt.Models.TaskItModels.Onus { id = 2, name = "Turn in timecard", content = "Give it to the boss by friday", hasLocation = true }); ret.Add(new TaskIt.Models.TaskItModels.Onus { id = 3, name = "Call Insurance about goats", content = "Ask them cost of coverage for 2 goats", hasLocation = false }); return ret; }
Now I went ahead and created a new Empty Web API Controller called TasksController. You will notice that all the methods within are named based off of convention. Meaning if my api gets a post request, it will look for a method called Post() automatically. Here is all the code I have in the Task Controller.
public class TasksController : ApiController { static List_oni = TaskIt.Models.TaskItInitializer.InitOni(); //uri: /api/courses/ public IEnumerable Get() { return _oni; } //uri: /api/courses/{id} public TaskIt.Models.TaskItModels.Onus Get(int id) { TaskIt.Models.TaskItModels.Onus ret = null; ret = (from c in _oni where c.id == id select c).FirstOrDefault(); return ret; } public TaskIt.Models.TaskItModels.Onus Post(TaskIt.Models.TaskItModels.Onus newOnus) { newOnus.id = _oni.Count(); _oni.Add(newOnus); return newOnus; } public void Put(int id, TaskIt.Models.TaskItModels.Onus updatedOnus) { TaskIt.Models.TaskItModels.Onus ret = null; ret = (from c in _oni where c.id == id select c).FirstOrDefault(); _oni.Remove(ret); _oni.Add(updatedOnus); } public void Delete(int id) { TaskIt.Models.TaskItModels.Onus ret = null; ret = (from c in _oni where c.id == id select c).FirstOrDefault(); if (ret != null) { _oni.Remove(ret); } } }
Nothing too complicated here. First I am filling up a list with my initialized model data, then I have a couple of GET methods, a POST method, a PUT method, and a DELETE method. All of your CRUD operations! What is happening inside the methods is really basic LINQ. This post is about how I talk to this from my website, not about LINQ, so if you are unfamiliar, shoot my a line and I can explain what is going on above in detail, or you can read up on LINQ.
Now to the good stuff: making our MVC Views talk to this thing. For my home page I just wanted the index to show my a list of all the tasks. Here is the javascript that accomplishes that:
So all I do is point an ajax request to the url of my api (api/tasks), and then on success, fill up an unordered list with list items that contain task.name. Naming is important here, not that name is lowercase, just like it is in the Model we created. This is how it knows what data to grab.
Next I wanted to get a task by id, which looks like this (This is in my Task View):
All I do to pass the id value is using razor to get it from my bound model. Super cool!
The best part for last, how to add some tasks via the client. This is done in the Create View:
This was something that up until seeing this I just couldn't figure out. Turns out that in $.ajax() you get specific the type of call it is. Here we specify POST, meaning that when it hits that API url, it is going to execute the Post() method. Then I simple specified the data by grabbing the values from the form, I alert the user it was added, then redirect to the home page using window.location.
So again, per my demo style: quick and dirty. Obviously a useful api would have error handling and return the standard status codes, which is something I did not implement here. So no, this code is not production ready, but yes it does show you have to tie it together end-to-end.