Content:
   - ASP.net tutorials:
1. Create simple web api
   - Create Model
   - Create Controller
   - Define simple routing
2. Access web service
   - Access web service from browser
   - Display web service data in browser with JavaScript/jQuery
   - Access web service from .net client - WebRequest
   - Access web service from .net client - HttpClient
3. Other
   - JSON or XML
   - Invoking web methods from Fiddler
   - Routing to method with attributes
   - Calling delete with http GET verb
   - Multiple GET methods


REST stands for REpresentational State Transfer

The concept represent an approach how data can be manipulated via webservice. REST leverages http verbs:
GET - retrieve item(s)
POST - add an item
PUT - update an item
DELETE - delete an item


Code examples: Service (VS 2010) | Client (VS 2012)

Web Api official site

ASP.net tutorials:


Tutorial on asp.net for Visual Studio 2012 (with sources, get only)
ASP. NET Web API Tutorial 02: CRUD Operations (with sources)

1. Create simple web api

This walkthrough demonstrates creating REST web service from scratch.
In Visual Studio 2010 select New Project, Web, ASP.net Empty Web Application
Right click on the solution, Add >> New Folder, name it Controllers
Right click on the solution, Add >> New Folder, name it Models
Right click on the Models folder, Add >> Class New Folder, name it Person

Create Model

Model represents the data structure that will be used to transfer and manipulate data.

C#
public class Person
{
    public String Name;
    public int Height;
}

Create Controller

Controller routes an incoming web requests to a method in the controller class. Web api maps http verb to beginning of controller method name and method argument name. The data would in most cases live in a database. For this example Person array will be used as it is sufficient for demonstration.

Right click on References, Add Reference, System.Web.Http
Right click on References, Add Reference, System.Net.Http 2.0
Right click on the Controllers folder, Add > Add New Class, name it PersonsController
.

C#
public class PersonsController : System.Web.Http.ApiController
{
    static Person[] s_persons = new Person[]
    {
        new Person() { Name = "John", Height=180},
        new Person() { Name = "Paul", Height=170}
    };

    
    public IEnumerable<Person> Get()   
    {
        return s_persons.ToArray();
    }
    
    public Person Get(int id)
    {
        return s_persons.Where(p => p.Id == id).FirstOrDefault();
    }

    public System.Net.Http.HttpResponseMessage Post(Person newPerson)
    {
        s_persons.Add(newPerson);

        // pass back to the caller success and new id (if database is used) 
        System.Net.Http.HttpResponseMessage result = new System.Net.Http.HttpResponseMessage(HttpStatusCode.OK);
        result.Headers.Location = new Uri("http://localhost:34460/api/persons/" + Convert.ToString(newPerson.Id));  // Id field would be autogenerated if database is used
return result; } public void Put(Person personArg) { Person person = m_persons.Where(p => p.Id == personArg.Id).FirstOrDefault(); person = personArg; } public void Delete(int id) { Person person = m_persons.Where(p => p.Id == id).FirstOrDefault(); s_persons.Remove(person); } }

Define simple routing

Routing on asp.net

Create App_Start folder.
Create WebApiConfig.cs under the folder.
http://myserver/api/persons will return list of all persons, because persons will be interpreted as PersonsController and a method starting with Get with no arguments will be used to return the data. {id} maps to id argument (in Get(int id)).

C#
using System.Web.Http;

namespace WebApiSimple
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}
Create Global.asax file in the root of the project

C#
<%@ Application Codebehind="Global.asax.cs" Inherits="WebApiSimple.WebApiApplication" Language="C#" %>
and Global.asax.cs as well. These files will register mapping defined in WebApiConfig when the application starts.

C#
namespace WebApiSimple
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            WebApiConfig.Register (System.Web.Http.GlobalConfiguration.Configuration);
        }
    }
}

2. Access web service

Access web service from browser

Right click on References, Add Reference, Newtonsoft.Json.dll (Otherwise the request will fail at runtime. You can get the .dll if you create a WepApi project from non empty template.)
Hit F5 in Visual Studio to start the web service
Open your web browser
type: http://myserver/api/persons to get list of persons
type: http://myserver/api/persons/1 to get person #1

Display web service data in browser with JavaScript/jQuery

The JavaScript code below will call http://myserver/api/persons and push the result to the html element with id="persons"

HTML
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"></script>
<script>
  function listAllPeople() 
  {
      $.getJSON('api/persons').done(
              function (people) 
              {
                  $.each(people, function (key, person) 
                  {
                      $('<li>', { text: person.Id + " " + person.Name } ).appendTo( $('#persons') );
                  });
              }
          );
  }
<script>

Access web service from .net client - WebRequest

You can access WebApi web service with HttpWebRequest
- Create a console app
- Inlude model.cs in the project

C#
HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create("http://localhost:34460/api/persons");
myHttpWebRequest.Method = "GET";
myHttpWebRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
myHttpWebRequest.ContentType = "application/json";
myHttpWebRequest.Accept = "application/json";

HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

// data in JSON format
System.IO.StreamReader myStreamReader = new System.IO.StreamReader(myHttpWebResponse.GetResponseStream());
string responseData = myStreamReader.ReadToEnd();

// deserialize the data
var p1 = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Person[]>(responseData);

Access web service from .net client - HttpClient

Calling a Web API From a .NET Client on asp.net

- Create console app
- Include model.cs in the projects
- Right click on References, Add Reference, System.Net.Http 2.0 (for HttpClient)
- add reference to System.Net.Http.Formatting 4.0 (ReadAsAsync) As HttpClient calls are asynchronous, async-await" is used.

C#
  static void Main()
  {
      string baseAddress = "http://localhost:34460/";
      CallWebService(baseAddress + "api/persons").Wait();
  }

  static async Task CallWebService(string baseAddress)
  {
      HttpClientHandler handler = new HttpClientHandler();
      handler.UseDefaultCredentials = true;  // needed for Windows authentication
      
      using (HttpClient client = new System.Net.Http.HttpClient(handler))
      {
          client.BaseAddress = new Uri(baseAddress);
          
          client.DefaultRequestHeaders.Accept.Clear();
          client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

          // get all items
          HttpResponseMessage httpResponseMsg = await client.GetAsync("");
          if (httpResponseMsg.IsSuccessStatusCode)
          {
              Person[] person = await httpResponseMsg.Content.ReadAsAsync<Person[]>();
          }

          // get one item
          httpResponseMsg = await client.GetAsync(baseAddress+"/1");
          if (httpResponseMsg.IsSuccessStatusCode)
          {
              Person person = await httpResponseMsg.Content.ReadAsAsync<Person>();
          }

          // add new - Post
          Person newPerson = new Person() { Id=3, Name = "George" };
          httpResponseMsg = await client.PostAsJsonAsync("", newPerson);
          if (!httpResponseMsg.IsSuccessStatusCode) { return; }
          
          Uri newlyAddedPersonUrl = httpResponseMsg.Headers.Location;

          // update existing
          newPerson.Name = "Ringo";   
          await client.PutAsJsonAsync(newlyAddedPersonUrl, newPerson);

          // delete existing
          await client.DeleteAsync(newlyAddedPersonUrl);
      }
  }

3. Other

JSON or XML

The data comes by default in JSON format

JSON
    
[{"Name":"John","Id":1},{"Name":"Paul","Id":2}]
If you want to get data in XML, you need to change the http header:

C#
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

XML
<ArrayOfPerson 
xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://schemas.datacontract.org/2004/07/WebApiSimple.Models">
<Person><Id>1</Height><Name>John</Name></Person>
<Person><Id>2</Height><Name>Paul</Name></Person></ArrayOfPerson>

Invoking web methods from Fiddler

As web browsers can send GET http request from the URL edit box, if you need to test POST, PUT or DELETE, you can use Fiddler
-Navigate to Composer tab
-Select "POST" verb
-Enter web service address, e.g. http://myserver/api/persons
-In the Request body section, enter [{"Name": "John","Id":1}]
-Click "Execute"
If you set a break point in the Post() method, the Visual Studio will stop the web service execution there.

Routing to method with attributes

if a method in a controller does not start with Http verbs, then it can be routed by using attributes. See Persons2Controller is source code

C#
[HttpGet]  
public IEnumerable<Person> RetrieveAll() {... }

[HttpPost]
public System.Net.Http.HttpResponseMessage Add(Person newPerson) {...}

[HttpPut]
public void Update(Person personArg) { ... }

[HttpDelete]
public void Remove(int id) { ... }

Calling delete with http GET verb

It is possible to call a delete method from a web browser. See Person3Controller is source code

C#
// enables http://localhost:34460/apiaction/persons3/delete/1
config.Routes.MapHttpRoute(
    name: "ActionApi",
    routeTemplate: "apiaction/{controller}/{action}/{id}",   // prefix "apiaction" is different in order to avoid conflict with api/persons/1 and api/persons/action
    defaults: new { id = RouteParameter.Optional }
);
....
[HttpGet]
public void Delete(int id) 
{
    Person person = s_persons.Where(p => p.Id == id).FirstOrDefault();
    s_persons.Remove(person);
}

Multiple GET methods

Sometime it is necessary to create methods that can return subset of data. There are 2 options how to call them:

C#
public Person GetOne(int id)
{
    return s_persons.Where(p => p.Id == id).FirstOrDefault();
}
public Person GetByName(string name)
{
    return s_persons.Where(p => p.Name == name).FirstOrDefault();
}
You can call GetByName either http://myserver/api/persons3?name=john or http://myserver/apiaction2/persons3/getbyname/john. The latter requires routing like below:

C#
config.Routes.MapHttpRoute(
    name: "ActionApi2",
    routeTemplate: "apiaction2/{controller}/{action}/{name}",
    defaults: new { id = RouteParameter.Optional }
);
because web api maps {name} to the name of the method argument "name". If you change the argument to name1, the web api will not be able to route the apiaction2/persons3/getbyname/john. http://myserver/api/persons3?name=john will be then routed to GetAll() method that does not have any argument.