Home > 2011 Fall DPS907, ASP.NET, Windows > Handle hypermedia in a WCF Web API service

Handle hypermedia in a WCF Web API service

October 11, 2011 Leave a comment Go to comments

You have worked with XML and JSON in WCF Web API services. This post will introduce you to the handling of hypermedia.

.

This post was most recently updated in October 2011.

.

XML and JSON are WCF Web API defaults

The WCF Web API services that you have created in the past work with XML and JSON data payloads. This capability is built in to the WCF Web API stack.

As a requestor, you indicate your desired data format:

  • The “accept” header tells the service about the data format that you will accept, so the server will deliver the data in that format (e.g. “application/json”)
  • The “content-type” header tells the service about the data format that you are sending in the request body with a POST or PUT request

.

When you write a web service method, it will have a return type, and some methods will accept arguments. The WCF Web API stack handles XML and JSON data formats by default.

The return type can be a data model object type, or a collection of them. Alternatively, a return type can be an HttpResponseMessage<T>, where T is a data model object type; this return type enables you to set other properties of the response message.

In either situation, the WCF Web API serializer takes care of serializing the data to the desired format.

For POST and PUT operations, where an object (or part of an object) is being sent to the method, the argument is a data model object type. A PUT handler will also include an argument which identifies the specific object to be updated. In addition, you can add an HttpRequestMessage argument, so that you can get access to properties of the request message.

In this situation, the WCF Web API serializer takes care of de-serializing the data sent with the request.

.

Delivering hypermedia

Delivering hypermedia – an image, a recording – is an uncomplicated task.

There are (at least) two ways to do this:

  1. Use an HttpResponseMessage object
  2. Use a MediaTypeFormatter

.

In this post, we will use an HttpResponseMessage object. (In a later post, we may cover the other way, using a MediaTypeFormatter.)

Assume that we have this scenario: We have a web service method, which handles GET. The method takes an argument, which is an identifier for a “photo” that will be delivered. The photo is (obviously) stored digitally, as a property of an entity. In addition, the photo’s MIME type is stored as a property of the entity.

Yes, the WCF Web API is still “new” in October 2011. Finding documentation and examples is a small challenge for an unreleased preview technology. However, we will persevere.

The return type of the method should (must) be HttpResponseMessage. It has two properties which must be set:

  • Content
  • Content.Headers.ContentType

.

The online help for the Content property tells us that it “Represents the content of a message. This corresponds to the entity body defined in RFC 2616.”

Its data type is System.Net.Http.Content, which is an abstract class. One of its concrete implementations is System.Net.Http.ByteArrayContent. When you examine this class’ documentation, you see that it has a constructor that uses a byte array. This matches the photo data that we have, so we can use it.

The online help for the Content.Headers.ContentType property is intended to hold the response’s “content-type” header value.

Its data type is System.Net.Http.Headers.MediaTypeHeaderValue. When you examine this class’ documentation, you see that it has a constructor that uses a string. This matches the photo MIME type that we have, so we can use it.

In summary, the method body has two lines of code that prepare the response. See the code sample below. Assume that the “photo” object is an typical model object, which has properties for storing hypermedia content and its MIME type.

    // Create a response object
    HttpResponseMessage response = new HttpResponseMessage();

    // Configure it with the photo content and the MIME type
    response.Content = new ByteArrayContent(photo.Content);
    response.Content.Headers.ContentType =
        new System.Net.Http.Headers.MediaTypeHeaderValue(photo.MIMEType);

    return response;

.

Accepting hypermedia

This course’s Lab 3 covers the task of accepting a photo in a WCF Web API service. It walks you through the coding tasks to re-purpose the Employees entity of the Northwind data store (or, in your copy, nwEmployees), so that you can store a modern format photo in the “Photo” property.

In general, when designing a web service method to accept hypermedia, you can obviously configure it for POST or PUT operations. The method body implementation will be almost the same (POST to a collection URI, and PUT to a specific object URI).

The method signature must include an HttpRequestMessage argument, so that you can get access to the request message headers and body. From the headers, you must extract the hypermedia’s MIME type. From the body, you must (obviously) extract the hypermedia.

In summary, the method body has two lines of code that accept the request data. See the code sample below. As above, assume that the “photo” object is a typical model object, which has properties for storing hypermedia content and its MIME type.

    // First, the hypermedia content...
    photo.Content = request.Content.ReadAsByteArray();
    // Next, the MIME type...
    photo.MIMEType = request.Content.Headers.ContentType.ToString();

.

Design considerations

When handling hypermedia, the way you design your methods is important.

Consider this scenario: You have an entity that describes a real-world object. It has many descriptive properties. It also has a hypermedia property (e.g. a photo).

When you GET a specific object, what do you expect to deliver/receive? Probably, a fully-serialized object, with the hypermedia data as part of the delivery package. This happens because the request’s default “accept” header will tell the service to serialize the object to XML or JSON.

What if you want the hypermedia only, in its native format (e.g. image/png)?

Should you create another method, which has another URI template (e.g. employee/{id}/photo)?

Or, should you enable the requestor to specify their desired data format in an accept header (e.g. accept: image/*), and process the request accordingly?

What about this slightly different scenario: You have an entity specifically for hypermedia (digital content). As such, it really is a container for hypermedia items. Typically, it is associated with other business entities.

How does this change your approach, given that a request for a specific hypermedia item fulfills the intent of the requestor?

The bottom line of all this is that you must consider your situation, and design and code accordingly. There’s no “one true way”, although some approaches are better than others.

.


.

.

.

About these ads
  1. No comments 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

Follow

Get every new post delivered to your Inbox.

Join 43 other followers

%d bloggers like this: