DPS907 notes – Tue Sep 30

Hypermedia-driven web API design.

.

Quiz today

Today’s session begins with a quiz.

.

Hypermedia-driven web API

Modern web APIs must be hypermedia-driven.

This means that the response will include:

  • the data that you expect, and
  • links that enable you – the requestor – to determine what to do next.

The web API author should not have to provide out-of-band documentation or knowledge to the user of the web API.

Your professor will use a web browser and web page analogy to help you understand this concept.

This concept was identified in the hypermedia constraint section of Roy Fielding’s PhD thesis. Please read:

Architectural Styles… thesis, by Roy Fielding; REST is discussed in Section 5.

REST APIs must be hypertext-driven, in which Roy reminds us about some design principles.

.

Data and metadata available to the web API designer and user

The following list is a brief reminder of the list of data items and metadata that are available to web service designers and users:

  • HTTP method
  • URI
  • Request headers
  • Response headers
  • Message body, in general
  • Representation (of a resource)

Today, you will learn something about these:

  • Link relations
  • The HTTP OPTIONS method
  • Representations that enable a user/requestor to learn about the data that’s needed to add a new resource

.

A brief discussion of ‘links’…

Web client programmers are familiar with HTML ‘link’ elements:

  • a
  • img
  • link

You also know that the “HT” part of HTML expands to “hypertext”.

What kind of data is at the other end of a link in HTML?

Text?

Always?

Or can it be an image, a video, or some other media?

Yes, certainly the data could be any kind of internet media type.

Therefore, to help you make progress learning this topic, simply change your understanding (of a link target’s data type) a bit, so that you begin to think of a link as a ‘hypermedia‘ link, and not just as a hypertext link.

.

How do we use links in a web API?

In a web API, links are used to tell the requestor about state transitions.

In other words, they tell the requestor what can be done next.

For example, assume that a requestor asks for a single-item resource (e.g. a product). The web service returns a representation (the data) for that resource. It would be nice to include data and/or metadata that would tell the requestor whether that resource could be modified, or deleted. Or whether it was possible to add a new resource to the resource’s parent/collection.

.

Link relations

The solution is to use link relations. Using this solution, the response includes links that can guide the user through state transitions.

This is what Roy Fielding means when he writes that “hypermedia [is] the engine of application state”.

A link is a data object, delivered in-band, with the representation. When you define a link in a web service, you must also define its relationship to the current object.

For example, by convention, a single object must include a link to itself:

  • The value of the URI (aka href) will be the item’s URI
  • The value of the relationship (aka rel) will be ‘self’

If the single object is part of a collection, it must also include a link to its parent/collection:

  • The value of the URI (aka href) will be the item’s parent/collection
  • The value of the relationship (aka rel) will be ‘collection’

This design ensures that the responses from your web service are self-describing.

The IANA has published a list of standardized link relations. You can create your own, but use the standard link relations until you gain more experience.

.

Code example for today’s topics

From the code example repository, look at LinkRelations.

.

Preview of our design and coding plan

In general, we will follow these steps:

  1. Start with an existing project that works well.
  2. Add new ‘resource model’ classes that support and enable link relations.
  3. For an entity, add new ‘resource model’ classes that include link relations. Add new AutoMapper definition(s).
  4. Update ‘controller’ code. Wrap the fetch result(s) in a resource model class that includes link relations, and configure the links.
  5. Add support for the HTTP ‘OPTIONS’ method.
  6. Configure an entry point URI for the web service.

.

Are there standards (for expressing link relations) that we must follow?

No.

In today’s example, we create our own representations.

In the future, we may look at HAL and/or Collection+JSON. It’s possible that you may use one of those in the future (or design your own). Mike Amundsen is very interested in hypermedia representations, and has much to offer in this topic area.

Let’s get started on the steps listed above…

.

Start with an existing project that works well

You will learn this topic more effectively if you use an existing project that works well.

Create a copy of that project, using the copy-then-rename technique you learned a few weeks ago.

.

Add new ‘resource model’ classes that support and enable link relations

Create a new source code file – perhaps named Links_vm – to the Controllers folder.

It will hold classes that support and enable link relations.

.

Overview of the design

There will be two versions of our design that supports link relations:

  1. a class for one item, and
  2. a class for a collection of items.

object-item-jsonFor one item (click the image to see it full-size in a new tab/window):

  • The class has two properties, ‘Links’ and ‘Item’
  • ‘Links’ is a collection of one or more Link objects
  • One Link is to ‘self’
  • Another Link is to its parent ‘collection’
  • ‘Item’ is the actual fetched result
  • The ‘Item’ also includes a Link to ‘self’

object-collection-jsonFor a collection of items (click the image to see it full-size):

  • The class has two properties, ‘Links’ and ‘Collection’
  • ‘Links’ is a collection of one or more Link objects
  • One Link is to ‘self’
  • ‘Collection’ is the actual fetched results
  • Each ‘Item’ in the collection includes a Link to ‘item’

.

Write the classes

We will need a Link class to model a hyperlink. At a minimum, it will need href and rel properties.

If you wished, in a future project, you could consider adding other properties, such as titlemethod, and content type.

.

Abstract class for the linked item

An abstract class will reduce the amount of code we write for resource models, if we also take advantage of generics and type injection. So, let’s do that: Write an abstract class, for a single item, that includes a T (type) parameter, as shown below:

abstract-class

.

Do the same to create an abstract class for a collection of items.

.

For an entity, add new ‘resource model’ classes that include link relations
Add new AutoMapper definition(s)

Our goal is to add a Link property to a suitable resource model class. That’s easy.

Then, remember to go the Global.asax.cs source code file and add an appropriate AutoMapper definition.

.

Update ‘controller’ code
Wrap the fetch result(s) in a resource model class that includes link relations,
and configure the links

Now, we have to update the code in a controller. We’ll focus on the get-all and get-one methods.

The beginning part of a controller method works the same. It calls a repository method, and a result is returned. The result can be a single item, a collection of items, or null.

Our goal is to ‘wrap’ the result(s) in the new resource model class that includes link relations.

Based on what you’ve learned earlier, the code in the method does the following:

  1. Create an object (item or collection) that supports link relations
  2. Add a Link to ‘self’
  3. If you’re configuring an ‘Item’, add a Link to the ‘collection’
  4. Set its ‘Item’ or ‘Collection’ property to the fetched result(s)
  5. If you’re configuring a ‘Collection’, add a Link to ‘item’ to each item
  6. Return the now-full-configured object

.

Deliver a template for an ‘add new album’ request

Here’s a scenario: A user of your web service wants to add a new ‘album’ object. What properties must be provided? Data types? Are there any other constraints?

One popular solution is to deliver a template with the response to the ‘get-all’ request. That’s the most natural place for it, because we’re already delivering a link relation for the collection.

How do we implement this? Two tasks:

  1. Add a resource model class for the template
  2. Add a property to the ‘get-all’ link relations container class for a template object

.

Add a resource model class for the template

Add a resource model class for the template. In the code example, it is named “AlbumAddTemplate”.

It has string properties. The property names match – exactly – the names of the properties in the “AlbumAdd” resource model class.

All properties have getters only. No setters. When initialized, the class object has all it needs to ‘tell a story’ to the user.

The property values will tell the user about the data they must send, including data types and other constraints (length, range, etc.).

.

Add a property to the ‘get-all’ link relations container class

Add a property to the ‘get-all’ link relations container class. Add a default constructor to initialize the property’s value.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

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

%d bloggers like this: