Web API basic CRUD Operations following HTTP principles

Web API makes building HTTP Services quite easy and pleasant since most of the hard work is taking place under it’s Framework’s umbrella. For example, when a client application makes a call to a Web API client, Web API can figure out by itself, what type of data passed to it and what type of data is expected to be returned. This transparency though, doesn’t mean that you don’t need to be aware of the basic HTTP Restful principles. We have seen in previous post the basics for starting with Web API but we weren’t so absolute as far as for the HTTP principles. This post will show you the right way to build HTTP Services with Web API. We will create a solution to support all CRUD operations Create – Read – Update – Delete on in-memory data. Let’s begin.

Create an ASP.NET 4 Web Application project, named HttpPrinciplesWithWebAPI selecting the Web API template. Delete the “ValuesController” inside the controllers folder and in it’s position create a new one named GroupController selecting the Empty API controller template. This controller will allow us to get Person objects from a group, add/delete a person to/from a group and lastly, update a group’s Person object. We need to create a Person class so paste the following code inside the class you created.

namespace HttpPrinciplesWithWebAPI.Controllers
{
    public class GroupController : ApiController
    {
    }

    public class Person
    {
        public int Id;
        public string FirstName;
        public string LastName;
        public int YearsInGroup;
    }
}

Let’s create our first Web API action method, the Get() one. We need some mock data so we will create a static variable of Person objects.

    public class GroupController : ApiController
    {
        public IEnumerable<Person> Get()
        {
            return group;
        }

        static List<Person> Group = InitGroup();

        private static List<Person> InitGroup()
        {
            var gr = new List<Person>();
            gr.Add(new Person { Id = 1, FirstName = "Christos", LastName = "Sakellarios", YearsInGroup = 7 });
            gr.Add(new Person { Id = 2, FirstName = "Anna", LastName = "Ioannou", YearsInGroup = 2 });
            gr.Add(new Person { Id = 3, FirstName = "Jason", LastName = "Smith", YearsInGroup = 3 });
            gr.Add(new Person { Id = 4, FirstName = "Helen", LastName = "Crouse", YearsInGroup = 10 });

            return gr;
        }
    }

    public class Person
    {
        public int Id;
        public string FirstName;
        public string LastName;
        public int YearsInGroup;
    }
}

We used the HTTP convention, that is we named our action method with a HTTP GET prefix. You could give it any name you wanted but you would have to annotate your method with a HttpGet attribute. Build your application and run it. Add a /api/group/ to the default url and make sure your Web API is on air.
webapicrud

If you can, test your Web API service through Fiddler too. This tool can provide you with important information about your HTTP Services.

webapicrud_1

Before start getting interesting in HTTP principles let’s change a little bit our Default View (the page is loaded when you start your application). Change Index.cshtml file under /Views/Home folder as follow.

<div id="body">
    <ul id="group">

    </ul>
</div>

@section scripts {
    <script>
        $.ajax({
            url: 'api/group',
            success: function (data) {
                var group = $('#group');
                for (var i = 0; i < data.length; i++)
                    group.append($('<li>' + data[i].Id + ' ' + data[i].FirstName +
                         ' ' + data[i].LastName + ' --> Years in Group: ' +
                         data[i].YearsInGroup + '</li>'));
            }
        });
    </script>
}

We deleted the most of the default content existed and add a simple ul element that each time you run your application, it is filled through an Ajax GET request to your Get Web API action method. Build and start your application.
webapicrud_2

Ok, it’s time to get some serious. Add the following Get(int Id) action method to your GroupController.

public Person Get(int Id)
        {
            var person = (from p in Group
                          where p.Id == Id
                          select p).FirstOrDefault();
            
            // If null should return a 404
            return person;
        }

This method will return a specific Person object according to Id value passed. You can see that I highlighted line 7. I made this for a reason. You should know that when you send an HTTP request to get a resource (e.g a specific Person), if that resource doesn’t exist, you should get back a 404 code telling you that the item you requested doesn’t exist. This is an HTTP principle. By default though this isn’t supported. Let’s test it. Request from Fiddler a valid Person and then an invalid. Check the code and value returned in the second case.

webapicrud_3

Request an invalid Person object, for example a person with Id=5

webapicrud_4

Instead of returing a null value and Status OK, let’s return a 404 code and a message telling that the Person object requested doesn’t exist. Change the Get(int Id) action method as follow.

public HttpResponseMessage Get(int Id)
        {
            HttpResponseMessage msg = null;
            var per = (from p in Group
                       where p.Id == Id
                       select p).FirstOrDefault();
            // If null should return 404
            if (per == null)
            {
                msg = Request.CreateErrorResponse(HttpStatusCode.NotFound, "Person not Found");
            }
            else
            {
                msg = Request.CreateResponse<Person>(HttpStatusCode.OK, per);
            }
            return msg;
        }

The message you must return must be of type HttpResponseMessage. If resource not found you create an message of that type using the Request.CreateErrorResponse function, passing as parameters a 404 code HttpStatusCode.NotFound and a custom message. If resource is found, you create a HttpResponseMessage message using the Request.CreateResponse function with HttpStatusCode.OK. Build your application and test the previous scenario again. Check the difference.

webapicrud_5

Let’s keep going. Same story with the POST action methods. Add a POST action to your GroupController in order to add a Person object to the in memory mock Person list, Group.

public void Post([FromBody]Person p)
        {
            Group.Add(p);
            // Should return a 201 with a location header
        }

The [FromBody] attribute means that new object’s value will come from the body. It could come for example from the query string. To post a Person object through Fiddler (we are going to see how you can post from your pages in other post), in the composer tab, select POST, in the Requested Headers add a Content-Type: application/json element and lastly, put the json value into the Requested Body. Finally press execute.

webapicrud_6

To return a 201 code telling that your resource was created, change your POST method as follow.

public HttpResponseMessage Post([FromBody]Person p)
        {
            Group.Add(p);
            // I should return a 201 and a location header
            var msg = Request.CreateResponse(HttpStatusCode.Created);
            msg.Headers.Location = new Uri(Request.RequestUri + "/" + p.Id.ToString());

            return msg;
        }

The only line I want to explain is the 6th. The msg.Headers.Location = new Uri(Request.RequestUri + “/” + p.Id.ToString()); will tell that new resource’s location will match the requested URL (when you sent the POST request, plus a /Id. In other words, we set the header location to listen the Get(int Id) Web API action method. Build and run your application. Check from Fiddler that a 201 Request Created Code is returned when you sent a valid POST request.

webapicrud_7

Well, this is pretty much the most important you need to know for HTTP GET and POST requests. One last thing I wanna show you, is how to sent xml POST requests. You may think that you setting the Content-Type: application/xml will be enough but that’s wrong. You need to give some more information about the XML object you want to POST. Check the follow image and you will understand.

webapicrud_8

That’s all for now. More interesting things on Web API coming on next posts so keep in touch. I hope you enjoyed the post. Download the project we created from here.

Advertisements


Categories: ASP.NET

Tags: , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Diary Of A Programmer

Because every day is worth noting

Chara Plessa

The purpose of this blog is to broaden my education, promote experimentation and enhance my professional development. Albert Einstein once said that “If you can’t explain it simply, you don’t understand it well enough” and I strongly believe him!

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Kumikoro

A Front End Developer's Blog

Muhammad Hassan

Full Stack Developer | ASP.NET | MVC | WebAPI | Advanced Javascript | AngularJS | Angular2 | C# | ES6 | SQL | TypeScript | HTML5 | NodeJS, MS candidate @LUMS, Grad & EX-Adjunct Faculty @NUCES-FAST, seasonal blogger & open-source contributor. Seattle, WA.

Software Engineering

Web development

IEvangelist

.NET, ASP.NET, C#, MVC, TypeScript, AngularJS

leastprivilege.com

Dominick Baier on Identity & Access Control

Happy DotNetting

In Love with Technology

Knoldus

Knols of experience to your advantage

knowshnet

Search - Read - Request - Share

Rahul's space

Learn, Share and Grow with me !

Dhananjay Kumar

Developer Evangelist @Infragistics | MVP @Microsoft |

SQL Authority with Pinal Dave

SQL Server Performance Tuning Expert

Conficient Blog

Random bits of tech from @conficient

Code! Code! Code!

SOLID & KISS

Code Wala

Designing and coding

Microsoft Mentalist

A way to start with Microsoft Technologies

Tony Sneed's Blog

A glimpse into the lives of Tony & Zuzana Sneed

%d bloggers like this: