Thursday, 26 February 2015

Building REST API with MVC 4 Web API - Part 1


Chuck Norris doesn't use web standards. The web conforms to him.
Modern web applications sometimes need to provide an API. In some cases the API is needed for internal use by the web application, as a page is being downloaded and subsequent JavaScript AJAX calls communicate with the server through API calls. In other cases, an API is offered to partners and third party developers, prominent examples being the Twitter and Facebook APIs.
.NET has provided tools and techniques for creating API-like solutions since version 1.0, using XML web services and Remoting, and later on with WCF. While WCF is still a viable technology choice and has its place, mostly in enterprise solutions, the industry and the developer community took a different, should I say simpler and more open approach to writing APIs.
The idea was to utilize the HTTP protocol to create what is known as REST API. The HTTP protocol defines various methods, such as GET, POST, PUT and DELETE, which can be used to specify the intent of an API call. An HTTP request may also contain parameters in the URL, include metadata in HTTP headers, and some HTTP methods can also carry a payload (through the request body). It seems that the HTTP protocol, while simple, is rich enough to provide the necessary building blocks for an API. Perhaps more importantly, in today's technology landscape, where there is no shortage of device form factors and platform choices, we need an API that can easily be consumed by any client. Due to the ubiquity of the HTTP protocol, REST APIs can be utilized by pretty much any form of client, no matter if it's a web application within a desktop browser, or a native app running on a smartphone.
While building a REST API in .NET has always been possible, simply due to the fact that .NET has always supported HTTP, there hasn't been any out-of-the-box way to easily do so. But REST assured (pun intended) .NET continuously evolves, and as of ASP .NET MVC 4 there is a built-in way to easily create a REST API. OK, let's get down to business. Enter MVC 4 Web API.

Creating a Simple Web API

Let's build a Web API project to maintain a database of Chuck Norris facts. First we need to create a new ASP .NET MVC 4 Web Application and select Web API as the project template.
Creating a project
Selecting project template
Let's define the following ChuckFact model, with Id, Text and Rating:
public class ChuckFact
{
    public int Id { get; set; }
    public string Text { get; set; }
    public int Rating { get; set; }
}
Now let's create a new controller, name it ChuckController and select Empty API Controller as the template.
Creating an API controller
For the sake of simplicity, we will store the facts in a collection within the controller for now. In real life scenarios, we should probably use a database...
public class ChuckController : ApiController
{
    private static List<ChuckFact> facts = new List<ChuckFact>()
    {
        new ChuckFact { Id = 1, Rating = 4, 
            Text = "Chuck Norris doesn't call the wrong number. You answer the wrong phone." },
        new ChuckFact { Id = 2, Rating = 3, 
            Text = "Chuck Norris counted to infinity. Twice." },
        new ChuckFact { Id = 3, Rating = 4, 
            Text = "When Alexander Bell invented the telephone he had 3 missed calls from Chuck Norris." },
    };
}
As it stands now our controller doesn't do anything because it has no methods. Let's start building it.

Supporting GET Requests

Let's add the following method to the controller:
public IEnumerable<ChuckFact> GetAllFacts()
{
    return facts;
}
The GetAllFacts method, as it name implies, simply returns all facts. Believe it or not, this tiny method is now part of our API offering. Build the project and browse to http://localhost:[port]/api/chuck (replace [port] with the actual port for your application) and you should get something like the following:
GET in browser
Note: if you use a different browser (I used Chrome), you might get the result in JSON instead of XML. More on that in part 3 of this tutorial, when we discuss content negotiation.
Let's talk about the URL: http://localhost:[port]/api/chuck. The chuck token in the URL specifies the controller class' name, sans the Controller suffix. This is how MVC knows to instantiate and invoke our controller. Don't worry about the api token, I'll cover it when we discuss routes. One interesting question however, is how does MVC know which method of the controller to invoke? Right now we have only one method but we could (and will soon) add more methods. The answer is that by default MVC looks for a method whose name starts with the HTTP request's method (i.e. GET), and which accepts the parameters specified in the request and supported by the route (more on routes below). Since browsers always make an HTTP GET request when you type a URL in their address bar, MVC could find a method that fits the bill. GetAllFacts starts with Get and has no parameters.
Let's add another GET method:
public ChuckFact GetFactByID(int id)
{
    ChuckFact fact = (from f in facts where f.Id == id select f).FirstOrDefault();
    if (fact == null)
        throw new HttpResponseException(this.Request.CreateResponse(HttpStatusCode.NotFound));

    return fact;
}
The GetFactByID method takes a parameter, id, and returns the fact that matches it, if any. Keep in mind that in Web API, we rely on the HTTP protocol to relay any error or status codes. Therefore, if the fact isn't found, we need to return a Not Found (404) status code. We do that by throwing an HttpResponseException that contains a response with the NotFound status code.
Now if we open the browser and navigate to http://localhost:[port]/api/chuck/1, we'll get the Chuck fact that has an id of 1. Based on the route, MVC can tell that the last token in the URL is an id so it looks for a controller method that starts with Get and takes an id, which matches GetFactByID.

Supporting POST Requests

Now let's add a method that allows creating a new fact. By convention we should use POST for that.
public HttpResponseMessage PostFact(ChuckFact fact)
{
    if (!this.ModelState.IsValid)
        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest));

    facts.Add(fact);
    HttpResponseMessage response = this.Request.CreateResponse(HttpStatusCode.Created, fact);
    response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = fact.Id }));

    return response;
}
Alright, let's talk about this method. When implementing a POST method, there isn't much to return (as opposed to a GET method whose whole raison d'etre is to return something). However, we should still return an HTTP response that indicates what happened. This is why the return type of the PostFact method is HttpResponseMessage.
The method first checks if the model is valid, and if it isn't, the method aborts the request and returns a Bad Request (400) status code. Our ChuckFact model doesn't currently specify any validity constraints, but it's good practice to check for validity now, in case we add such constraints in the future.
Next we store the new fact, and are ready to return a response. While not mandated by MVC Web API, RFC 2616 stipulates that we should return a status code of Created (201) if a resource has been created on the server and provide a URL to the newly created resource through a Location HTTP header. We therefore create a response and specify the URL that can be used to fetch the new Chuck fact. Note that we do not create the URL manually. Instead, we invoke the Link method and provide it with the name of the route and the parameters value. The default route created by the project template is named "DefaultApi" and it takes an optional parameter for the id.
To test this method, we can't use a browser (at least not in the manner we are used to). Typing a URL in the address bar generates a GET request, but now we want to test a POST request. There are several tools that can assist us here. I chose to use the ever popular Fiddler, which can be downloaded for free.
Testing POST with Fiddler
In the drop down left to the URL, I selected POST. You can use Fiddler to test requests of any HTTP method. For the URL, I specified the path to our controller. I wanted to use the JSON format to specify the new Chuck fact, so I had to include the Content-Type request header and set it to application/json. I could omit this header, in which case I would have to URL encode the new fact (even though it's in the request body rather than in the URL). And finally the request body has the actual new fact, in JSON format. Now we can click the Execute button to send the request to the server. We can then see the request on the left pane of Fiddler, and select it to easily inspect what was sent and what was received.
POST result
The response was 201 (Created) and we can also spot the Location header with the URL to the new Chuck fact (at the very bottom). Pasting this URL in a browser (or using Fiddler to issue the GET request) should return the newly added fact. Everything went well, Chuck would be proud!

Supporting PUT and DELETE Requests

To update an entity, we typically use the PUT HTTP method. To delete an entity we use the DELETE HTTP method (shocking, I know). Here are the corresponding controller methods:
public HttpResponseMessage PutFact(ChuckFact fact)
{
    if (!this.ModelState.IsValid)
        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest));

    ChuckFact existFact = (from f in facts where f.Id == fact.Id select f).FirstOrDefault();
    if (existFact == null)
        throw new HttpResponseException(this.Request.CreateResponse(HttpStatusCode.NotFound));

    facts.Remove(existFact);
    facts.Add(fact);
    return this.Request.CreateResponse(HttpStatusCode.NoContent);
}

public HttpResponseMessage DeleteFact(int id)
{
    ChuckFact fact = (from f in facts where f.Id == id select f).FirstOrDefault();
    if (fact == null)
        throw new HttpResponseException(this.Request.CreateResponse(HttpStatusCode.NotFound));

    facts.Remove(fact);
    return this.Request.CreateResponse(HttpStatusCode.NoContent);
}
The methods are self-explanatory. The only thing worth mentioning is that upon success, they return a status code of NoContent (204). This is one of the options stipulated by RFC 2616 when PUT or DELETE are successful. The other option is OK (200), which should also contain the actual entity (the updated / deleted Chuck fact), as was done in the Post method.

A Few Words About Routes

The project template for the Web API project contains a file named WebApiConfig.cs in the App_Start folder. This file has the WebApiConfig class and its Register method, which is called from the Application_Start method in Global.asax. By default, the method performs the following route configuration:
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);
The name of the route is an arbitrary string, but recall that we used this name from in thePostFact method when we had to to create a URL. routeTemplate is probably the most interesting parameter. It defines that the route must have the api token and it has placeholders for the controller name and the id parameter. Note that all of the URLs we used in our testing were in the form of http://localhost:[port]/api/chuck or http://localhost:[port]/api/chuck/[id]. The reason we can omit the id lies in the last parameter of the routing config, defaults. It specifies that the id parameter is optional.
Note that any parameters of simple types that are not part of the route, or are optional, can be specified in a query string form. For example, http://localhost:[port]/api/chuck/1 is equivalent to http://localhost:[port]/api/chuck/?id=1. This also means that if you're OK with using query strings instead of URL path tokens for your Web API parameters, you don't need to create additional routes if you have methods that require parameters other than id. For example, here is a method that returns all Chuck facts of a certain minimum rating:
public IEnumerable<ChuckFact> GetFactsByRating(int minRating)
{
    return from f in facts where f.Rating >= minRating select f;
}
We can invoke this API method with a URL such as http://localhost:[port]/api/chuck/?minrating=4. The part up to the query string matches our route above (it doesn't contain an id and that's fine as the id is optional), so MVC knows to invoke our controller. It then sees that this is a GET request and it contains the minrating parameter in the query string, so it looks for a method whose name starts with Get and which takes a minRatingparameter (case insensitive). The GetFactByRating method matches the criteria and therefore gets invoked.

Summary

In this tutorial we learned how to use MVC Web API to create a REST API that supports CRUD (create, read, update, delete), and also educated ourselves on a few important Chuck Norris facts. Our Web API can now be used by any client whose platform supports HTTP, which means pretty much any client... In the next parts of this tutorial, I will discuss routes, parameters and methods in more detail, as well as ways to customize the Web API framework, and will even show how to host Web API without using IIS. Stay tuned.
P.S - Chuck Norris can make HTTP requests without network connectivity.

Sunday, 22 February 2015

ASP.NET Web API vs. Windows Communication Foundation (WCF)

As described by Microsoft:

"ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework."
"Windows Communication Foundation (WCF) is Microsoft’s unified programming model for building service-oriented applications. It enables developers to build secure, reliable, transacted solutions that integrate across platforms and interoperate with existing investments."
Although these descriptions are brief, side-by-side it is easy enough to determine how Microsoft tries to distinguish the two frameworks: Web API is for RESTful services and WCF is for "existing investments."  Let's dive into the details about why Microsoft has two service frameworks and when each should be used...

The Basics: SOAP and REST (and OData)

SOAP

Without getting too deep into its history, Simple Object Access Protocol (SOAP) is a Microsoft invented protocol that was meant to create a structured way of sending and receiving data over the wire.  This protocol is one of the main foundations of WCF and utilizes XML to create services with typed data and methods.  In the typical scenario, a Web Services Description Language (WSDL) file is created from service code and is provided, usually through a static URL, to the client.  The client uses this WSDL file to understand what methods are available on the service, how to call them, and what the classes of the returned objects will be.  This is a very action-driven model that focuses on what actions a service is a capable of performing.
Example Service Endpoint: http://www.yourcompany.com/SOAPService.Svc

REST

REpresentational State Transfer (REST) is not a protocol, but an architecture and design pattern for building and calling web services.  This is the pattern that Web API was designed to utilize to build web services.  It is a very resource-drivenarchitecture that exposes endpoints based on objects and not functions.  RESTful services also make use of the standard HTTP methods and constructs to exchange data; using GET, POST, PUT, DELETE, and sometimes PATCH a caller can denote which action to perform on the object being accessed at the requested endpoint.  Query parameters and content in the body of the request can also provide ways to pass parameters to the service.

OData

Open Data Protocol (OData) is another Microsoft defined protocol (now an open web standard).  This protocol extends AtomPub and is a resource-driven model.  It allows querying resources on the web service using different endpoints to denote the resource type and query parameters to specify how to filter the results.  OData services can also be built using Web API and are usually considered a type of REST service.
Example Query: http://www.yourcompany.com/api/OData.svc/Resources()?$filter=ResourceType eq Images&$top=20

The Decision: Web API or WCF?

Client Interoperability

RESTful services, and therefore Web API by extension, are focused on simplicity and being lightweight.  Any application that is able to access a website can access a RESTful service by using the same HTTP calls.  This differs from SOAP where the client must understand the web service by utilizing the WSDL file.  The WSDL configuration adds some complication and requires additional logic that might not be readily available on many devices (phones, smart TVs, etc.) and programming languages and frameworks.

Coding Overhead

On the client side it is simple to call a RESTful service using HTTP, but hardcoding resource endpoints, serializing and deserializing objects, and recreating custom classes that are returned can be difficult; all of that low level interaction with the web service is abstracted in SOAP services and is "magically" done for you.  On the service side, WCF tends to be more configuration heavy and typically requires extensive XML work to get it configured just right. Web API, conversely, has a more standard "out-of-the-box" setup that works for most services, and provides the capability to provide customizable services that extend the base services, such as media type formatters that handle serialization, when needed.

Speed/Bandwidth

Since RESTful services only use basic HTTP, the request and response packets are generally smaller than SOAP request and response packets which package parameters, objects, metadata, etc. in a thick, usually XML, payload.  Sometimes this is an important consideration when dealing with mobile or low bandwidth devices.  The simple HTTP request/responses also tend to be more human readable than SOAP requests/responses*, although that is not as significant since these services are usually consumed programmatically.
*The caveat to this statement is that WCF services can be customized to use a simpler format, although this isn't the standard implementation.  WCF can also utilize HTTP and other protocols, although, again, that is not the standard implementation.

Functionality/Purpose

As described above, SOAP services should be very action-driven and REST/OData services should be very resource-driven.  Although any action-driven service can be converted into a resource-driven service, there are some cases where one SOAP call could translate into multiple REST calls; this creates additional overhead in calling the service, increases the complexity of the client's code, and can potentially cause data issues in poorly designed systems.  Well designed REST services should be able to mitigate this with indirect actions.  As an example, a SOAP call that purchases an item for a customer could do the following:
  1. Create an order
  2. Reduce the quantity of an item in stock
  3. Create a new shipping task
  4. Update the customer's information and order history
That single SOAP call could translate to four different REST calls updating each of those resources, or, in a properly designed system, one create (POST) PurchaseOrder call that then triggers actions to update the other resources as necessary.  Ultimately, RESTful services should be simple and atomic, but SOAP services, for better or for worse, have the flexibility to be bulky and complex.
REST services are more "discoverable" than SOAP services since they can be freely accessed in URLs.  Good REST services are also intuitive enough to figure out, both in regard to endpoints and idempotency.  As an example, ifwww.yourcompany.com/api/Employees/1 provides the employee with an ID of 1, then it is easy enough to determine that www.yourcompany.com/api/Employee/2 provides the employee with an ID of 2.  Assuming you know the service also contains customers, it is again easy enough to determine thatwww.yourcompany.com/api/Customer/1 provides the customer with and ID of 1.  Similarly intuitive, using the HTTP actions can reflect the idempotency of a call in REST services.  A PUT operation, for example, should be idempotent since you are updating fields with specific values.  A similar call in a SOAP service may not be as easy to determine whether it is idempotent or not.

Security

WCF and Web API both have security standards that are accepted.  In WCF, highly typed security frameworks and helpers are available to provide enterprise-level security, including security that meets the Web Services Interoperability Organization (WS-I) standards.  In Web API, typical web standards are used for security such as Basic and Token authentication, as well as more complex web standards such as OAuth.  If properly implemented, security in either framework will be just as good as the other, although some companys prefer and often require specific security implementations.  RESTful services, however, do provide a little more flexibility than SOAP that can be useful when authenticating with an external service such as Windows Live IDs, Google, Facebook, or Twitter.

Conclusion

Unfortunately, I cannot say that one is better than the other.  Fortunately, there is a fairly straightforward way of determining which framework to use when building a new web service.  Go through the paragraphs above and determine who is using the service, how they are using it, and how the service will be built and scaled.  My general rule of thumb is: If it's an internal/intranet web service, use WCF; if it's an external/internet web service, use Web API.

Thursday, 19 February 2015

Embedding HTML5 video is still pretty hard


In the early days of the HTML5 movement, I wrote the first major cross-browser compatibility shim for HTML5 <video> and <audio> tags. It was called html5media.js.
At the time, I assumed that the shim would be obsolete within a few years, just as soon as major browsers adopted a common standard and video codec. Unfortunately, the shim is still used by hundreds of thousands of people each day, and embedding video is just as confusing as ever.

So how do I embed video in my site?

Please, just save yourself a headache, and host your video on YouTubeVimeo, or some other third party service. They employ some very clever people who’ve solved all the problems with embedding video.

Haha… no, really. How do I embed video in my site?

Take a deep breath. In order to embed video in your site, there are four major groups of people you need to keep happy:
  1. Modern browsers using commercial codecs (Chrome, Safari, IE9+)
  2. Modern browsers using open-source codecs (Firefox, Opera)
  3. Legacy browsers (IE8)
  4. Under-powered mobile devices (iPhone 3GS, cheap Android)
For the rest of this post, I’ll take you through the steps required to allow an increasing number of people to watch your video.

Embedding video for modern browsers with commercial codecs

The simplest video embed code you can possibly use is as follows:
1
2
3
4
5
6
<!DOCTYPE html>
<html>
    <body>
        <video src="video.mp4" width=640 height=360 controls>
    </body>
</html>
Congratulations! Your video will now play in:
  • Chrome
  • Safari (inc. Mobile Safari on iPhone 4+)
  • IE9+

Adding support for legacy browsers

In order to make your video work in legacy browsers, you need to add a script tag to the <head>of your document. This script, the venerable html5media.js, will provide a Flash video player fallback for legacy browsers.
1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
    <head>
        <script src="http://api.html5media.info/1.1.5/html5media.min.js"></script>
    </head>
    <body>
        <video src="video.mp4" width=640 height=360 controls></video>
    </body>
</html>
Note: The syntax of the <video> tag has changed to include an explicit closing tag, to avoid confusing older browsers.
Fantastic! Your video will now play in:
  • Chrome
  • Safari (inc. Mobile Safari on iPhone 4+)
  • IE9+
  • IE8 (via Flash)
  • Firefox (via Flash)
  • Opera (via Flash)
At this point, the vast majority of internet users will be able to play your video. The only people who’ll be left out will be:
  • Firefox or Opera users without Flash
  • Owners of under-powered mobile devices.

Adding Flash-free support for modern browers with open-source codecs

To allow Firefox and Opera users to view your video using their native players, you need to transcode your video into an open-source format, and embed both files in your page. I’d recommend using the free Miro Video Encoder to transcode your video to WebM format. You can then embed it using the following code:
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
    <head>
        <script src="http://api.html5media.info/1.1.5/html5media.min.js"></script>
    </head>
    <body>
        <video src="video.mp4" width=640 height=360 controls>
            <source src="video.mp4"></source>
            <source src="video.webm"></source>
        </video>
    </body>
</html>
Note: We’re adding explicit closing tags to <source> elements to avoid confusing legacy browsers.
Unbelievable! Now your video will play in:
  • Chrome
  • Safari (inc. Mobile Safari on iPhone 4+)
  • IE9+
  • IE8 (via Flash)
  • Firefox (via Flash)
  • Opera (via Flash)
It’s just the owners of under-powered mobile devices who’ll struggle to play your video now.

Adding support for under-powered mobile devices

The latest mobile devices support high-resolution video, but cheap Android phones and iPhone 3GS will refuse to play anything higher-resolution than about 320 x 180 pixels. To keep these devices happy, you need to transcode your video to this lower resolution. Miro Video Encoderhas a built-in iPhone 3GS setting, so just use that.
Now you can embed your video using the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
    <head>
        <script src="http://api.html5media.info/1.1.5/html5media.min.js"></script>
    </head>
    <body>
        <video src="video.mp4" width=640 height=360 controls>
            <source src="video.mp4" media="only screen and (min-device-width: 568px)"></source>
            <source src="video-low.mp4" media="only screen and (max-device-width: 568px)"></source>
            <source src="video.webm"></source>
        </video>
    </body>
</html>
OMG! What a monster! But now everyone will be able to play your video!
  • Chrome
  • Safari (inc. Mobile Safari on iPhone 4+)
  • IE9+
  • IE8 (via Flash)
  • Firefox (via Flash)
  • Opera (via Flash)
  • Mobile Safari (iPhone 3GS)
  • Android Browser (inc. cheap Android phones)

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...