ASP.NET Web API Introduction

A web API is just an application programming interface (API) over the web (that is, HTTP). When the resources of an application can be manipulated over HTTP using the standard HTTP methods of GET, POST, PUT, and DELETE, you can say that the application supports a web API for other applications to use. Because HTTP is platform-agnostic, HTTP services can be consumed by disparate devices across different platforms. A central concept of HTTP services is the existence of resources that can be identified through a uniform resource identifier (URI). If you equate resources to nouns, then actions on a resource can be equated to verbs and are represented by the HTTP methods such as GET, POST, PUT, and DELETE. For an application that deals with the Users of an organization, each User is a resource the application deals with. Let us see how an User’s details can be retrieved with an HTTP service. The URI is http://server<port>/API/Users/1000. It includes the User ID and serves as an identifier to the resource, which is an User in this case. Actions on this resource are accomplished through the HTTP verbs. To get the details of an User, you will perform an HTTP GET on the URIhttp://server<port>/API/Users/1000. To update this User, the request will be an HTTP PUT on the same URI. Similarly, to delete this User, the request will be an HTTP DELETE request, again on the same URI. To create a new User, the request will be an HTTP POST to the URI without any identifier (http://server<port>/API/Users).

 In the case of POST and PUT, the service must be passed the User data or the resource representation. It is typically XML or JSON that is sent as the HTTP request message body. An HTTP service sends responses in XML or JSON, similar to the request. For example, a GET to http://server<port>/API/Users/1000 results in a response containing JSON representing the User with an ID of 1000.

HTTP service responds with the HTTP status code indicating success or failure. For example, if the User with identifier 1000 does not exist, the HTTP status code of 404 - Not found will be returned. If the request is successful, the HTTP status code of 200 - OK will be returned.

The ASP.NET Web API framework enables you to create HTTP-based services through the powerful ASP.NET MVC programming model familiar to many developers. So, we have the URI http://server/hrapp/Users/1000, and a client issues a GET. To respond to this request, we need to write code somewhere that retrieves the User details for 1000. Obviously, that code has to be in some method in some C# class. This is where the concept of routing comes into play. The class in this case typically will be one that derives from the ApiController class, part of the ASP.NET Web API framework. All you need to do is to create a subclass of ApiController, say UsersController, with a method Get(int id). The ASP.NET Web API framework will then route all the GET requests to this method and pass the User ID in the URI as the parameter. Inside the method, you can write your code to retrieve the User details and just return an object of type User. On the way out, the ASP.NET Web API framework will handle serialization of the User object to JSON or XML. The web API is capable of content negotiation: A request can come in along with the choices of the response representation, as preferred by the client. The web API will do its best to send the response in the format requested. In the case of requests with a message payload such as POST, the method you will need to define will be Post(User User) with a parameter of type User. The ASP.NET Web API framework will deserialize the request (XML or JSON) into the User parameter object for you to use inside the method. The web API dispatches a request to an action method based on HTTP verbs. ASP.NET MVC 4 ships as part of Visual Studio 2012 and as an add-on for Visual Studio 2010 SP1. ASP.NET Web API is a part of MVC 4.0. There is a new project template called WebAPI available to create web API projects. You can have both API controllers and MVC controllers in the same project.

Choosing ASP.NET Web API or WCF

If you have worked with the .NET Framework for any amount of time, you must have encountered the term WCF (Windows Communication Foundation), the one-stop framework for all service development needs in the .NET Framework. Why the new framework of ASP.NET Web API then?

The short answer is that ASP.NET Web API is designed and built from the ground up with only one thing in mind—HTTP—whereas WCF was designed primarily with SOAP and WS-* in mind, and Representational State Transfer (REST) was retrofitted through the WCF REST Starter Kit. The programming model of ASP.NET Web API resembles ASP.NET MVC in being simple and convention-based, instead of requiring you to define interfaces, create implementation classes, and decorate them with several attributes. However, ASP.NET Web API is not supposed to supersede WCF.

 It is important to understand the coexistence of WCF and ASP.NET Web API. WCF has been around for a while, and ASP.NET Web API is a new kid on the block, but that does not mean WCF is meant to be replaced by ASP.NET Web API. Both WCF and ASP.NET Web API have their own place in the big picture. ASP.NET Web API is lightweight but cannot match the power and flexibility of WCF. If you have your service using HTTP as the transport and if you want to move over to some other transport, say TCP, or even support multiple transport mechanisms, WCF will be a better choice. WCF also has great support for WS-*.

However, when it comes to the client base, not all platforms support SOAP and WS-*. ASP.NET Web API–powered HTTP services can reach a broad range of clients including mobile devices. The bottom line: it is all about trade-offs, as is the case with any architecture.

 Let’s try to understand the differences in programming models by looking at a simple example: an User service to get an User of an organization, based on the User ID.

WCF code (see Listing 1-1) is voluminous, whereas ASP.NET Web API code (see Listing 1-2) is terse and gets the job done.

 Listing 1-1. Getting an User the WCF Way
[ServiceContract]
public interface IUserService
{
[OperationContract]
[WebGet(UriTemplate = "/Users/{id}")]
User GetUser(string id);
}
public class UserService : IUserService
{
public User GetUser(string id)
{
return new User() { Id = id, Name = "Shabir Hakim" };
}
}
[DataContract]
public class User
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
// other members
}
Listing 1-2. Getting an User the ASP.NET Web API Way
public class UserController : ApiController
{
public User Get(string id)
{
return new User() { Id = id, Name = "Shabir Hakim" };
}
}



A couple of things are worth mentioning here: First, the web API is exactly the same as a normal MVC controller except that the base class is ApiController. Features of MVC that developers like, such as binding and testability, which are typically achieved through injecting a repository, are all applicable to a web API as well. If you are experienced with ASP.NET MVC, you may be wondering how different a web API is; after all, the MVC controller’s action method can also return JsonResult. With JsonResult action methods, a verb is added to the URI (for example, http://server/Users/get/1234), thereby making it look more like RPC style than REST. Actions such as GET, POST, PUT, and DELETE are to be accomplished through HTTP methods rather than through anything in the URI or query string. ASP.NET Web API also has far superior features, such as content negotiation. ASP.NET MVC’s support for JsonResult is only from the perspective of supporting AJAX calls from the JavaScript clients and is not comparable to ASP.NET Web API, a framework dedicated to building HTTP services. The following are the scenarios where ASP.NET Web API as the back end really shines and brings the most value to the table:

  1. Rich-client web applications: ASP.NET Web API will be a good fit for rich-client web applications that heavily use AJAX to get to a business or data tier. The client application can be anything capable of understanding HTTP; it can be a Silverlight application, an Adobe Flash–based application, or a single-page application (SPA) built using JavaScript libraries such as JQuery, Knockout, and so on, to leverage the power of JavaScript and HTML5 features.
  2. Native mobile and non-mobile applications: ASP.NET Web API can be a back end for native applications running on mobile devices where SOAP is not supported. Because HTTP is a common denominator in all the platforms, even the native applications can use a .NET back-end application through the service façade of a web API. Also, native applications running on platforms other than Windows, such as a Cocoa app running on Mac, can use ASP.NET Web API as the back end.
  3. Platform for Internet of Things (IOT): IOT devices with Ethernet controllers or a Global System for Mobile Communications (GSM) modem, for example, can speak to ASP.NET Web API services through HTTP. A platform built on .NET can receive the data and do business. Not just IOT devices, but other HTTP-capable devices such as radio frequency ID (RFID) readers can communicate with ASP.NET Web API.

ASP.NET Web API is meant for developing web APIs. In other words, although it can technically work, it is not the right candidate for supplementing your ASP.NET web application’s AJAX needs, especially when the AJAX use cases are very few.

Let Create WebAPI

Exposing simple in-memory List over HTTP

Let us do something practical here. you will create a simple web API that basically exposes an in-memory List<User> over HTTP, for a client application to manipulate the list members. I know this is just limited or small concept but i am sure this will give you clear concept about what webAPI is and how to use it or will give you  understanding how to use the ASP.NET Web API framework to build your web API.

  1. Run Visual Studio and create a new project like shown below Give the project a name of Users and click OK, as shown in Figure 1-1.
  2. Select the ASP.NET Web template and click OK. You will see lots of option, as shown in Figure 1-2.



  3. Choose the Controllers folder in the Solution Explorer of Visual Studio. Select Add ➤ Controller and give a name of UsersController for the controller. Leave the option Empty API Controller selected in the Template dropdown and click Add, as shown in Figure 1-3. Notice that the generated controller class inherits from ApiController, a class that is part of the ASP.NET Web API framework.
  4. Right-click the Models folder in the Solution Explorer of Visual Studio. Select Add ➤ Class to add a new class with a name of User
  5. Add the code shown in Listing 1-3 to the User class. Listing 1-3. The User Class
    public class User
    {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    }
    
  6. Create a new static field at the controller level, as shown in Listing 1-4. This will be the list that our web API exposes over HTTP. Figure 1-3. Adding a controller
    Listing 1-4. The List of Users
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http;
    using Users.Models;
    namespace Users.Controllers
    {
    public class UsersController : ApiController
    {
    private static IList<User> list = new List<User>()
    {
    new User()
    {Id = 1000, FirstName = "Shabir", LastName = "Hakim" },
    new User()
    {Id = 1001, FirstName = "Raja", LastName = "Public"},
    new User()
    {Id = 1002, FirstName = "Rani", LastName = "Private"},
    new User()
    {Id = 1003, FirstName = "Shabir", LastName = "Robert" }
    };
    // Action Get methods go here
    // GET api/Users
    public IEnumerable<User> Get()
    {return list;}
    // GET api/Users/1000
    public User Get(int id)
    {return list.First(e => e.Id == id);}
    }
    }
    
  7. Add five action methods, as shown in Listing 1-5. It is important to use the name as shown in the listing. You will learn more about why you must follow this naming convention in the nextSection . Listing 1-5. The Action Methods to Get, Post, Put, and Delete Users
    // GET api/Users
    public IEnumerable<User> Get()
    {
    return list;
    }
    // GET api/Users/1000
    public User Get(int id)
    {
    return list.First(e => e.Id == id);
    }
    
    // POST api/Users
    public void Post(User User)
    {
    int maxId = list.Max(e => e.Id);
    User.Id = maxId + 1;
    list.Add(User);
    }
    // PUT api/Users/1000
    public void Put(int id, User User)
    {
    int index = list.ToList().FindIndex(e => e.Id == id);
    list[index] = User;
    }
    // DELETE api/Users/1000
    public void Delete(int id)
    {
    User User = Get(id);
    list.Remove(User);
    }
    
  8. Build the Visual Studio solution and run it by pressing F5. Internet Explorer, which is the default browser associated with Visual Studio, shows the home page with a URL of http://localhost:55778/. (My ASP.NET Web API project uses port 55778. Your project will use a different one and based on that, Internet Explorer will display a different port in the URL.)
  9. In the address bar type http://localhost:<port>/api/Users Replace <port> with the actual port your application runs on.

    NoteNote:As you work through theSection s in this tutorial, you will create several new projects, and the port will change every time you create a new ASP.NET MVC project. Remember to replace the port specified in the example code with your application’s actual port.

  10. When Internet Explorer asks if you want to open or save, click Open and choose Notepad as the program to open the file. Notepad will display JSON as shown in Listing 1-6. I have formatted the output for your reading pleasure.

  11. You can also get the details of a specific User by performing an HTTP GET on http://localhost:63482/Api/Users/1000. In this case, you get the JSON output shown in Listing 1-7.

  12. If you see the preceding two JSON outputs, you have just created your first web API and exposed the in-memory list of Users to the outside world over HTTP! Currently, we have tested only the HTTP GET but we will test the other methods in the upcomingSection s.

    NoteNote: The steps outlined in thisSection are the fundamental steps to create a basic ASP.NET Web API project. In the rest of theSection s throughout this tutorial, I will not repeat these steps, but you will need to perform them as and when required to get your project to a point where you can start working on the steps of a specificSection . Once you have set up a project, you can reuse it for multipleSection s, and there is no need to create a new project for everySection .

    >

Choosing Configuration over Convention

In thisSection , you will override the default behavior of the ASP.NET Web API framework in selecting the action method of the controller based on the HTTP method. The default convention is to give the action method the same name as the HTTP method or to name the method so that it starts with the HTTP method. For example, I used Get in the previousSection to handle HTTP GET. So the action method can be GetUser, or GetAllUsers, or GetUserById. Similarly, the action methods of Post, Put, and Delete will respectively handle HTTP POST, PUT, and DELETE. Of course, an action method with a weird name such as PutTheLimeInTheCokeYouNut can still be matched by the ASP.NET Web API framework to handle HTTP PUT because the method name begins with Put, which corresponds to HTTP PUT. To override this convention, you can apply the AcceptVerbs attribute or use the equivalent shorthand notation of HttpGet, HttpPost, HttpPut, HttpDelete, and so on.


  1. Comment out all the action methods in the UsersController class that we created in Exercise 1.2, retaining only the static list. The controller class after this change will look like Listing 1-8. Listing 1-8. The UsersController Class with Action Methods Commented Out
    public class UsersController : ApiController
    {
    private static IList<User> list = new List<User>()
    {
    new User()
    {Id = 1000, FirstName = "Shabir", LastName = "Human" },
    new User()
    {Id = 1001, FirstName = "Raja", LastName = "Public"},
    new User()
    {Id = 1002, FirstName = "Rani", LastName = "Private"},
    new User()
    {Id = 1003, FirstName = "John", LastName = "Robert" }
    };// Following action methods are commented out
    }
  2. Add the RetrieveUserById method to the UsersController class, as shown in Listing 1-9. Listing 1-9 shows two action methods that do not follow the naming convention mapped to the required HTTP method through the usage of AcceptVerbs and HttpGet attributes. You can copy and paste one of the methods but not both, for the obvious reason that the code will not compile with duplicate method names.
    Listing 1-9. Using AcceptVerbs
    [AcceptVerbs("GET")]
    public User RetrieveUserById(int id)
    {
    return list.First(e => e.Id == id);
    }
    [HttpGet]
    public User RetrieveUserById(int id)
    {
    return list.First(e => e.Id == id);
    }
    
  3. Build the Visual Studio solution and run it by pressing F5. Internet Explorer, which is the default browser associated with Visual Studio, shows the home page.
  4. In the address bar, type http://localhost:63482/Api/Users/1000. When Internet Explorer asks if you want to open or save, click Open and choose Notepad as the program to open the file. Notepad displays JSON, the same as in the previousSection . The only difference now is the action method that handles the GET request; it is now the RetrieveUserById method and not the Get method.
  5. You can use custom names for action methods handling other verbs as well. See Listing 1-10 for the UpdateUser method that handles PUT. You do not need to copy and paste this code into the UsersController that you are working on, since you will not test PUT methods until the next Topic . Listing 1-10. Action Method Handling PUT [HttpPut] public void UpdateUser(int id, User User) { int index = list.ToList().FindIndex(e => e.Id == id); list[index] = User; } It is possible to switch the selection of an action method from the HTTP style, which is along the lines of REST, to the RPC style, which is based on the action method, as specified in the URI. This is same way that ASP.NET MVC selects action methods.
  6. Comment out the RetrieveUserById action method you added earlier. At this point, the UsersController class will have only the static field list and will be same as the code shown in Listing 1-8. The following code simply repeats Listing 1-8 for your easy reference.
    public class UsersController : ApiController
    {
    private static IList<User> list = new List<User>()
    {
    new User()
    {Id = 1000, FirstName = "Shabir", LastName = "Human" },
    new User()
    {Id = 1001, FirstName = "Raja", LastName = "Public"},
    new User()
    {Id = 1002, FirstName = "Rani", LastName = "Private"},
    new User()
    {Id = 1003, FirstName = "John", LastName = "Robert" }
    };
    // All action methods are commented out
    }
    
  7. Add the methods shown in Listing 1-11 to UsersController. The listing shows the code for implementing two RPC-style methods. The URIs corresponding to RpcStyleGet and GetUserRpcStyle action methods are respectively http://localhost:55778/ api/Users/rpcstyleget and http://localhost:63482/Api/Users/ getUserrpcstyle/1000. Listing 1-11. Action Methods RPC Style
    [HttpGet]
    public IEnumerable<User> RpcStyleGet()
    {
    return list;
    }
    public User GetUserRpcStyle(int id)
    {
    return list.First(e => e.Id == id);
    }
  8. Of course, for this RPC-style selection of an action method to work, you have to make an entry in the WebApiConfig.cs file under App_Start folder, as shown in Listing 1-12. Make sure the code in bold type is added before the existing MapHttpRoute, as shown in the listing.
    Listing 1-12. Configuring RPC-Style Action Methods
    public static class WebApiConfig
    {
    public static void Register(HttpConfiguration config)
    {
    config.Routes.MapHttpRoute(
    name: "RpcApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );
    config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );
    }
    }
  9. Build the Visual Studio solution and run it by pressing F5. Internet Explorer displays the home page.
  10. Type http://localhost:63482/Api/Users/getUserrpcstyle/1000 in the address bar of the browser. When Internet Explorer asks if you want to open or save, click Open and choose Notepad as the program to open the file. Notepad displays JSON, just as in the previousSection . The only difference now is that the action method that handles the GET request is GetUserRpcStyle, which is part of the URI route data. Review the URI you used. It is no longer in the REST style. The action method is also part of the URI and is in RPC-style.
  11. Now that you have tested RPC-style action methods, remove the RPC-style mapping from the WebApiConfig class, as shown in Listing 1-13. The code shown with strikethrough is what you will delete from the WebApiConfig class. Listing 1-13. WebApiConfig Class with RPC-style Mapping Removed
    public static class WebApiConfig
    {
    public static void Register(HttpConfiguration config)
    {
    config.Routes.MapHttpRoute(
    name: "RpcApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );
    config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );
    }
    
    
    Now, you will change the default route template to see how ASP.NET Web API works.
  12. Change the WebApiConfig class under App_Start folder to modify the route template, as shown in Listing 1-14. Listing 1-14. WebApiConfig Class with Default Route Template Modified
    public static class WebApiConfig
    {
    public static void Register(HttpConfiguration config)
    {
    config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "webapi/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );
    }
    }
    
  13. Build the Visual Studio solution. Type http://localhost:55778/api/Users in the address bar of the browser.
  14. You will see the message “The resource cannot be found.” Basically, ASP.NET Web API is not able to route your GET request to the correct controller and action method.
  15. Type http://localhost:55778/webapi/Users in the address bar of the browser.
  16. It starts working. So, it is clear that the route template defined in the Register method of WebApiConfig.cs file under App_Start folder is important for the framework to choose the controller and the action method. By default, the route template comes with api, which is a literal path segment, and two placeholder variables, {controller} and {id}. Because a project created using the Web API template can have both API controllers and MVC controllers, the api literal path segment is used by default to avoid collisions with MVC routing.
  17. Change the WebApiConfig class under App_Start folder, as shown in Listing 1-15. The literal Webapi is changed to api, and a new placeholder variable orgid with a constraint is introduced. Listing 1-15. WebApiConfig Class with a New Variable in Route Template
    public static class WebApiConfig
    {
    public static void Register(HttpConfiguration config)
    {
    config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{orgid}/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional },
    constraints: new { orgid = @"\d+" }
    );
    );
    }
    }
    
  18. Rebuild the solution and press F5 to run it. Type http://localhost:55778/api/Users in the address bar of the browser. You’ll see the message 404 —The webpage cannot be found.
  19. Type http://localhost:55778/api/123/Users in the address bar of the browser. It starts to work again. Notice the additional segment with a value of 123 in the URI.
  20. In UsersController, comment out all the action methods, retaining only the static field. Add a new action method, as shown in Listing 1-16. Listing 1-16. UsersController with Action Method Receiving OrgID
    public User Get(int orgid, int id)
    {
    return list.First(e => e.Id == id);
    }
    
  21. Add a breakpoint to this action method. Rebuild the solution and run the project by pressing F5.
  22. Type http://localhost:55778/api/123/Users/1000 in the address bar of the browser.
  23. When the execution breaks, inspect the parameters: orgid and id. They are both mapped to 123 and 1000 respectively.
  24. Type http://localhost:55778/api/abc/Users/1000 in the address bar of the browser. You get a 404 —The webpage cannot be found. So, by adding a new {orgid} variable and adding a constraint, we have made sure the URI must include a new URI segment immediately after api and that it must be a number. When we define an action parameter matching the placeholder variable name, the URI path is mapped to the action parameter.
  25. Restore the WebApiConfig class to its out-of-box state, like so:
    public static class WebApiConfig
    {
    public static void Register(HttpConfiguration config)
    {
    config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );
    }
    }
    

Working by the Rules of HTTP

In thisSection , you will create a web API that plays by the rules of HTTP. It is natural for a developer to assume that the CRUD operations create, read, update, and delete correspond to the HTTP methods POST, GET, PUT, and DELETE. Equating GET with reading and DELETE with deleting are correct, but POST for creating and PUT for updating are not fully accurate. GET is guaranteed not to cause any side effects and is said to be nullipotent; nothing happens to the system’s state, even when it is called multiple times or not called at all. In other words, the system state will be the same for all the following scenarios: (1) the method was not called at all, (2) the method was called once, and (3) the method was called multiple times. PUT and DELETE are idempotent; the effect to the system state will be the same as that of the first call, even when they are called multiple times subsequently. There is no stopping, for example, if you implement the logic that changes the state of the system in the action method handling GET. It is not only a deviation from the standards, it is also an inferior implementation from a security standpoint.

Note  Note The HTTP specification (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1) calls GET a “safe” method. It also mentions GET under idempotent methods, because a nullipotent method is also idempotent. I use the term nullipotent because it clearly indicates that GET must be “safe”; that is, there must not be any side-effects.

The usage of the appropriate HTTP status codes is another important aspect of building HTTP-compliant services. By default, 200 – OK is returned, indicating success. 401 – Not authorized is sent when a user requests an action on a resource that requires the user to be authenticated and that user has either not provided the credentials or provided invalid credentials. Sending a 200 – OK and a message in the response body that authentication failed is not something an HTTP-compliant service will do. In thisSection , I show you the standard way of implementing the CRUD action methods in your HTTP-compliant ASP.NET Web API.

Retrieving Resource(s)

The HTTP GET method is useful for retrieving resource representations. For example, http://server/api/Users lists all Users, while http://server/api/Users/1000 retrieves a specific User (1000 is the identifier of the User). GET methods have no request body. The response body is a JSON/XML representation of the resource requested—either a list of Users or a specific User. ASP.NET Web API has out-of-box formatters for JSON and XML, but it is not hard to create a custom formatter. I’ll cover custom formatters in Topic 3 and Topic 5. It is very important not to implement logic in a GET method that changes the state of the system, because HTTP GET is nullipotent.

  1. Comment out all the action methods in UsersController from the previousSection . At this point, the UsersController class will have only the static field list and will be same as the code shown in Listing 1-8 earlier. The following code is just a repeat of Listing 1-8 for your easy reference.
    public class UsersController : ApiController
    {
    private static IList<User> list = new List<User>()
    {
    new User()
    {
    Id = 1000, FirstName = "Shabir", LastName = "Hakim"
    },
    new User()
    {
    Id = 1001, FirstName = "Raja", LastName = "Public"
    },
    new User()
    {
    Id = 1002, FirstName = "Rani", LastName = "Private"
    }
    };
    // All action methods are commented out
    }
    
  2. Add a new action method to handle GET, as shown in the Listing 1-17. It retrieves one specific User based on the ID. If there is no User matching the ID, 404 - Not Found status code is returned. Listing 1-17. Retrieval of a Specific User by ID
    public User Get(int id)
    {
    var User = list.FirstOrDefault(e => e.Id == id);
    if(User == null)
    {
    throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return User;
    }
    
  3. Rebuild the solution and make a GET request by typing a URI in the address bar of Internet Explorer. The URI should contain an User ID for which there is no corresponding resource, such as http://localhost:63482/Api/Users/45678. 404 - Not Found is returned, and Internet Explorer shows the same with the message that The webpage cannot be found. It is possible to retrieve a list of Users matching a condition. For example, you can filter the Users based on the Country to which they belong. In this case, the Country is sent in the query string: http://localhost:port/api/Users?Country=2. ASP.NET Web API matches the query parameter (Country) to the parameter on the action method. If the Country in the request is not a valid Country number, the 422 - Unprocessable Entity status code is returned. This is not a standard HTTP status code but is defined in the HTTP extension for WebDAV. It is acceptable to send the status code 400 - Bad Request as well.
  4. To the User model class, add a new property, as shown in Listing 1-18. Listing 1-18. User Class with Country
    public class User
    {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Country { get; set; }
    }
    
  5. Modify the IList<User> list in UsersController, as shown in Listing 1-19, to populate the Country property. Listing 1-19. User List with Countrys
    private static IList<User> list = new List<User>()
    {
    new User()
    {
    Id = 1000, FirstName = "Shabir", LastName = "Hakim", Country = 2
    },
    new User()
    {
    Id = 1001, FirstName = "Raja", LastName = "Public", Country = 3
    },
    new User()
    {
    Id = 1002, FirstName = "Rani", LastName = "Private", Country = 2
    }
    };
    
  6. Add the action method shown in Listing 1-20 to UsersController. Listing 1-20. Retrieval of Users by Country
    public IEnumerable<User> GetByCountry(int Country)
    {
    int[] validCountrys = {1, 2, 3, 5, 8, 13};
    if (!validCountrys.Any(d => d == Country))
    {
    var response = new HttpResponseMessage()
    {
    StatusCode = (HttpStatusCode)422, // Unprocessable Entity
    ReasonPhrase = "Invalid Country"
    };
    throw new HttpResponseException(response);
    }
    return list.Where(e => e.Country == Country);
    }
    
  7. Rebuild the solution and make a GET request by typing the URI http://localhost:55778/api/Users?Country=2 in the address bar of Internet Explorer. The resulting JSON will include only Shabir and Rani. It is possible to apply multiple conditions based on parameters. For example, http://localhost:port/api/ Users?Country=2&lastname=Smith can be used to filter for all Smiths in Country number 2. The action method in this case can have two parameters, Country and lastName. An alternative is to use a model class that represents the input, as shown in Listing 1-21. For ASP.NET Web API to bind the query parameters to the complex type Filter, you must use the FromUri attribute. You’ll learn more about this in Topic 5.
  8. Comment out all the action methods in UsersController and add the action method shown in Listing 1-21. Listing 1-21. Retrieving an User by Applying Two Conditions
    public IEnumerable<User> Get([FromUri]Filter filter)
    {
    return list.Where(e => e.Country == filter.Country &&
    e.LastName == filter.LastName);
    }
    
  9. Create a class named Filter, under the Models folder. The code should be as shown
    in Listing 1-22.
    Listing 1-22. The Filter Class
    public class Filter
    {
    public int Country { get; set; }
    public string LastName { get; set; }
    }
    
  10. Rebuild the solution and make a GET request by typing the URI http://localhost:55778/api/Users?Country=2&lastname=Hakim in the address bar of Internet Explorer. Pay attention to the upper case ‘H’. Now, the resulting JSON will include only Shabir.

Creating a Resource with a Server-Generated Identifier

resource such as an User can be created by an HTTP POST to the URI http://localhost:port/api/Users. There is no ID that is specified in the URI. In this case, the request body contains the JSON/XML representation of the resource being added, which is the new User. The response body will be a JSON/XML representation of the resource, the new User who was just added into the system. The difference between the request and the response representations is that the User ID that was generated by the system is present in the response representation, while it is absent in the request. Hence, this type of resource creation is analogous to INSERT SQL statements on tables with the primary key generated by the database engine, with the client having no say on what the new ID can be. InSection 1.2, we returned the User type. In response to this, the ASP.NET Web API framework returned a 200 – OK status code, and we did not have control over the status code that must be returned. By returning an object of type HttpResponseMessage, we can have better control over what is returned to the client, including the HTTP status code. In the case of resource creation using POST, returning the HTTP status code of 201 – Created and the URI of the new resource created in the location response header as shown in Listing 1-23 will better conform to HTTP/1.1 than sending a blanket 200 – OK status code.

Listing 1-23. Creating an User using HTTP POST
public HttpResponseMessage Post(User User)
{
int maxId = list.Max(e => e.Id);
User.Id = maxId + 1;
list.Add(User);
var response = Request.CreateResponse<User>(HttpStatusCode.Created, User);
string uri = Url.Link("DefaultApi", new { id = User.Id });
response.Headers.Location = new Uri(uri);
return response;
}

You will need a tool like Fiddler to create a POST request and view the response. For the purpose of thisSection , Listing 1-24 shows the response message for POST. If you are already familiar with Fiddler, you can issue a POST and inspect the response. I’ll cover Fiddler in Topic 2.

Listing 1-24. Response Status Code and Headers
HTTP/1.1 201 Created
Date: Mon, 26 Mar 2013 07:35:07 GMT
Location: http://localhost:63482/Api/Users/1004
Content-Type: application/json; charset=utf-8

Note  Note T o create a resource using HTTP POST, you must use a URI without the ID, for example, http://localhost:port/api/Users. Requesting a POST on a URI with an ID, for example http://localhost:port/api/Users/1004, where 1004 is an ID that does not exist, must be rejected with a 404 - Not Found.See Section 1.4.5.

Creating a Resource with a Client-Supplied Identifier

resource such as an User can be created by an HTTP PUT to the URI http://localhost:port/api/ Users/1004, where the User with an ID of 1004 does not exist until this PUT request is processed. In this case, the request body contains the JSON/XML representation of the resource being added, which is the new User. The response body can be a JSON/XML representation of the resource, the new User that was just added into the system. But in this case the response body can be omitted, since there will not be any difference between the request and the response resource representations. Listing 1-25 shows the code to create User using PUT.

Listing 1-25. Creating an User using HTTP PUT
public HttpResponseMessage Put(int id, User User)
{
if (!list.Any(e => e.Id == id))
{
list.Add(User);
var response = Request.CreateResponse<User>
(HttpStatusCode.Created, User);
string uri = Url.Link("DefaultApi", new { id = User.Id });
response.Headers.Location = new Uri(uri);
return response;
}
return Request.CreateResponse(HttpStatusCode.NoContent);
}

This type of resource creation using PUT is applicable for scenarios where the client decides the key or the ID for the resource. Hence, this type of resource creation is analogous to INSERT SQL statements that specify the primary key.
NoteNote: To test POST, PUT, and DELETE, you will need a tool like Fiddler, covered in Topic 2.

Overwriting a Resource

resource can be overwritten using HTTP PUT. This operation is generally considered the same as updating the resource, but there is a difference. To issue a PUT request, you must send the representation of the resource in the request in its entirety. Partial updates are not allowed. For example, this SQL statement: UPDATE User SET last_name = 'Schindler' where User_id = 1000 updates only one field in the record. This type of functionality must not be supported by PUT, which is analogous to deleting a record and reinserting it, in the SQL world. A PUT request is issued to an URI, for example http://localhost:port/api/Users/1000, where the User with an ID of 1000 already exists in the system. Listing 1-26 shows the action method handling PUT to overwrite a resource.

Listing 1-26. Overwriting an User using HTTP PUT
public HttpResponseMessage Put(int id, User User)
{
int index = list.ToList().FindIndex(e => e.Id == id);
if (index >= 0)
{
list[index] = User; // overwrite the existing resource
return Request.CreateResponse(HttpStatusCode.NoContent);
}
else
{
list.Add(User);
var response = Request.CreateResponse<User>
(HttpStatusCode.Created, User);
string uri = Url.Link("DefaultApi", new { id = User.Id });
response.Headers.Location = new Uri(uri);
return response;
}
}

Updating a Resource

resource such as an User in our example can be updated by an HTTP POST to the URI http://server/api/Users/1000, where the User with an ID of 1000 already exists in the system. Listing 1-27 shows the action method handling POST to update an User. If an User of the ID same as the incoming ID is not present, the request is rejected with a 404 - Not Found status code.

Listing 1-27. Updating an User using HTTP POST
public HttpResponseMessage Post(int id, User User)
{
int index = list.ToList().FindIndex(e => e.Id == id);
if (index >= 0)
{
list[index] = User;
return Request.CreateResponse(HttpStatusCode.NoContent);
}
return Request.CreateResponse(HttpStatusCode.NotFound);
}


Deleting a Resource

Similar to PUT, DELETE is idempotent as well. After the first request to delete a resource, which is successful, if there are subsequent DELETE requests to the same resource, we will have a problem in finding the resource in subsequent requests. Should we send 200 – OK for first request and 404 – Not Found for subsequent requests? 204 – No Content can be uniformly sent for the first as well as subsequent requests, as shown in Listing 1-30. ASP.NET Web API ensures the status code of 204 - No Content is returned, since the return type of the action method is void.

Listing 1-30. Deleting an User
public void Delete(int id)
{
User User = Get(id);
list.Remove(User);
}

Consuming ASP.NET Web API

One of the greatest benefits of ASP.NET Web API is its reachability. A broad range of clients in disparate platforms can consume your web API, leveraging the support HTTP enjoys across platforms and devices. In this Topic , I cover the topic of client applications consuming your web API. I’ve limited the coverage to .NET clients—a console application, a Windows Presentation Foundation (WPF) application, and a JavaScript client running in the context of a browser.

Calling a Web API from a Console Application

In thisSection , you will call your web API from a C# console application. To call the web API, you can use System.Net.WebClient, or even WebRequest and WebResponse classes, or for that matter any other library you are familiar with. You just need HTTP capabilities to call a web API. However, this example will use HttpClient, the modern HTTP client that is available from the .NET framework version 4.5 (ported to .NET 4.0 as well). You can issue more than one request through a single HttpClient instance, and you get the async features of .NET 4.5 by default, helping you manage and coordinate multiple requests.

  1. You will use the solution from Topic 10 for this Section . For this reason, a prerequisite to start working on this Topic is that you complete all theSection s in Topic 10.
  2. If you prefer, you can make a copy of the entire folder containing both the solutions (Robusta.UserManager and Robusta.Broker) and other files from Topic 10 and start making changes for this Topic .
  3. Open the Robusta.UserManager solution in Visual Studio 2012.
  4. In the Robusta.UserManager.WebApi.Core project, open UsersController and comment out the AuthorizeByTimeSlot attribute on the Get(int) action method. 5.
  5. In the Solution Explorer, right-click Solution ‘Robusta.UserManager’ and choose Add ➤ New Project. Under Visual C# templates, select Windows and choose Console Application. Give it a name of Robusta.UserManager.WebApi.Client.ConsoleApp. Right-click this project in the Solution Explorer and select Set As Startup Project.
  6. Right-click References under the Robusta.UserManager.WebApi.Client.ConsoleApp project and select Manage NuGet Packages. Search for the package Microsoft.AspNet. WebApi.Client, select the package in the search results, and click Install.
  7. Add the following project reference to Robusta.UserManager.WebApi.Client. ConsoleApp: a. Robusta.UserManager.WebApi.Dto
  8. Add the code in Listing 11-1 to the Main method in the Program class of the Robusta.UserManager.WebApi.Client.ConsoleApp project. Add a breakpoint in the closing brace of the Main method. Listing 11-1. The Console Application Main Method
    using System;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using Robusta.UserManager.WebApi.Dto;
    class Program
    {
    static void Main(string[] args)
    {
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost/UserManager/api/");
    HttpResponseMessage response = client.GetAsync("Users/1").Result;
    Console.WriteLine("{0} - {1}", (int)response.StatusCode, response.ReasonPhrase);
    if (response.IsSuccessStatusCode)
    {
    var User = response.Content.ReadAsAsync().Result;
    Console.WriteLine("{0}\t{1}\t{2}",
    User.Id,
    User.FirstName,
    User.LastName,
    User.CountryId);
    }
    } // Add a breakpoint on this line
    }
    
  9. Rebuild the solution and press F5.
  10. 10. It works and returns a 200 - OK and the User data.
  11. We read the response as response.Content.ReadAsAsync<UserDto>().Result;. Since the web API returns UserDto and this class is part of a separate assembly, Robusta.UserManager.WebApi.Dto, we are able to just reference the assembly and use the same type in both the server and the client side.
  12. Also, by getting the Result property of the Task object, we block the Main method. The main thread waits for the response to come back and resumes processing.
  13. Add the code from Listing 11-2 to the end of the existing Main method.
    Listing 11-2. POSTing an User
    UserDto newUser = new UserDto()
    {
    FirstName = "Jeff",
    LastName = "Rock",
    CountryId = 2
    };
    response = client.PostAsJsonAsync<UserDto>
    ("http://localhost/UserManager/api/Users", newUser)
    .Result;
    if (response.IsSuccessStatusCode)
    {
    Console.WriteLine(response.Content.ReadAsStringAsync().Result);
    if (response.Headers != null)
    Console.WriteLine(response.Headers.Location);
    }
    Console.WriteLine("{0} - {1}", (int)response.StatusCode, response.ReasonPhrase);
    
  14. Rebuild the solution and press F5. The code we just added makes a POST and adds a new User resource. HttpClient makes it easy to add the request headers using strongly typed APIs instead of having to work with strings all the time.
  15. Add the code from Listing 11-3 to the end of the Main method. It requests an XML representation of the User resource and writes the XML to the console.
    Listing 11-3. Adding Accept Headers
    client.DefaultRequestHeaders.Accept.Add(
    new MediaTypeWithQualityHeaderValue("application/json", 0.8));
    client.DefaultRequestHeaders.Accept.Add(
    new MediaTypeWithQualityHeaderValue("application/xml", 0.9));
    response = client.GetAsync("Users/1").Result;
    Console.WriteLine("{0} - {1}", (int)response.StatusCode, response.ReasonPhrase);
    if (response.IsSuccessStatusCode)
    {
    Console.WriteLine(response.Content.ReadAsStringAsync().Result);
    }
    
  16. In the Robusta.UserManager.WebApi.Core project, open UsersController and apply the Authorize attribute on the Get and Post action methods, like so:
    [Authorize]
    public HttpResponseMessage Get(int id) { ... }
    [Authorize]
    public HttpResponseMessage Post(UserDto UserDto) { ... }
    
  17. Rebuild the solution and press F5 to run the console client application. You get 401 - Unauthorized for all three calls from the Main method. The Authorize attribute expects authenticated identity, and we are not passing any credentials for the message handlers to establish identity. To send the credentials, we could add the code directly in the Main method. Instead, let us use a client-side message handler. Just as on the server side, you can have message handlers on the client side as well.
  18. Add a class named CredentialsHandler to the Robusta.UserManager.WebApi.Client.ConsoleApp project, as shown in Listing 11-4.
    Listing 11-4. The Client Message Handler
    using System;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    public class CredentialsHandler : DelegatingHandler
    {
    protected override async Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request,
    CancellationToken cancellationToken)
    {
    var headers = request.Headers;
    if (headers.Authorization == null)
    {
    string creds = String.Format("{0}:{1}", "jqHakim", "p@ssw0rd!");
    byte[] bytes = Encoding.Default.GetBytes(creds);
    var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(bytes));
    headers.Authorization = header;
    }
    return await base.SendAsync(request, cancellationToken);
    }
    }
  19. Comment out the line HttpClient client = new HttpClient(); in the Main method of the Program class in the Robusta.UserManager.WebApi.Client.ConsoleApp project and add the following line:
    HttpClient client = HttpClientFactory.Create(new CredentialsHandler());
    We use HttpClientFactory to create the client instance in order to specify the handler to be run in the client pipeline.
  20. Rebuild the solution and press F5 to run the console client application. All three web API calls work now.

    NoteNote: Because we set the header from the message handler, the header is set for every request, with the handler being called every time we make a web API call. If you set the header using the DefaultRequestHeaders property of HttpClient, setting it once is enough.

Summary

The ASP.NET Web API framework enables you to create HTTP-based services through the powerful ASP.NET MVC programming model familiar to developers. The programming model of ASP.NET Web API is similar to ASP.NET MVC in that it is simple and convention-based.
In this Topic , you first created a simple web API that exposes an in-memory list over HTTP, for a client application to manipulate the list members. Then you overrode the default behavior of the ASP.NET Web API framework in selecting the action method of a controller based on the HTTP method. The default convention is to name the action method either same as the HTTP method or starting with the HTTP method name. To override this convention, you applied the AcceptVerbs attribute. You also created RPC-style action methods instead of the default REST-style action methods.
Finally, you created a web API that plays by the rules of HTTP. It is natural for a developer to assume the CRUD operations create, read, update, and delete correspond to the HTTP methods POST, GET, PUT, and DELETE. You saw that it’s correct to equate GET for reading and DELETE for deleting, but POST for creating and PUT for updating are not fully accurate. A resource can be created as well as modified by both POST and PUT. A resource can be created by an HTTP POST to the URI without the ID. A resource can also be created by an HTTP PUT to the URI with the ID. If the User with the specified ID does not already exist, the new resource is created with the client-specified ID. So, the former method of using an HTTP POST is analogous to INSERT SQL statements on tables with the primary key generated by the database engine and the latter case is analogous to INSERT SQL with the primary key specified by the caller.
A resource can be overwritten using HTTP PUT. This operation is generally regarded as updating the resource but there is a difference. To issue a PUT request, you must send the representation of the resource in the request in its entirety. Partial updates are not allowed. PUT is analogous to deleting a record and re-inserting it, in the SQL world. HTTP POST can support partial updates to a resource. But there is a separate PATCH method. Request for Comments (RFC) 5789 “PATCH Method for HTTP” adds this new HTTP method, PATCH, to modify an existing HTTP resource. In the next Topic , you will see how to test the POST, PUT and DELETE methods that you created in this Topic , using the web debugging tool Fiddler. Also, you will learn how to implement tracing for your code as well as for the framework code.