Need help with WebApi.Hal?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

212 Stars 104 Forks Microsoft Public License 177 Commits 0 Opened issues


Adds support for the Hal Media Type (and Hypermedia) to Web Api

Services available


Need anything else?

Contributors list


Adds support for the Hal Media Type (and Hypermedia) to Web Api

HAL Specification

Getting Started with WebApi.Hal

First thing first, WebApi.Hal is a media formatter. So to get started you have to register the Hal Media formatters:

GlobalConfiguration.Configuration.Formatters.Add(new JsonHalMediaTypeFormatter());
GlobalConfiguration.Configuration.Formatters.Add(new XmlHalMediaTypeFormatter());

Once those are registered, you can start defining your resources. In WebAPI.Hal, you always return

from your ApiControllers.

Your representations should all inherit from

or if you are returning a collection a
or if you are returning a resource with multiple embedded resources, inherit from
and add properties for the embedded resources which might include lists of resources of the form
. See the sample.


The link class represents hypermedia on a representation. It looks like this:

public class Link
    public string Rel { get; set; }
    public string Href { get; set; }
    public string Title { get; set; }
    public bool IsTemplated { get; set; }
    public Link CreateLink(...);

The thing which makes this class special is it's support for templates. For example:

var link = new Link("beers", "/breweries/{id}/beers");

Notice the {id}, this allows you to return a templated link as hypermedia. But you can also turn it into an absolute link really easily:

Brewery brewery;
link.CreateLink(new { id = brewery.Id });

URI Templates adhere to RFC6570, as per the HAL specification.

Register WebAPI routes

Once you have done the work of defining all your link templates, register your routes in the ordinary MVC WebApi manner. See the sample project for an example.

LinkTemplates class

A nice place to keep your Links is in a static class called LinkTemplates, with nested classes for each resource your application has, for example:

public static class LinkTemplates {
    public static class Beers {
        /// /beers/{id}
        public static Link Beer { get { return new Link("beer", "/beers/{id}"); } }

    /// <summary>
    /// /beers?page={page}
    /// </summary>
    public static Link GetBeers { get { return new Link("beers", "/beers{?page}"); } }


The sample is available at:


This is the base class for all representations your api returns. It has an abstract method you must override,

abstract void CreateHypermedia();

In the constructor, set the Rel property, as this generally doesn't change based on context.

In CreateHypermedia() you could register a self link, but it's done automatically for you if you don't. Register other hypermedia that your resource should always have. Other context sensitive hypermedia should be added in the API controller.

Here is an example of the Beer CreateHypermedia override (from the example project, the

public Beer()
    Rel = LinkTemplates.Beers.Beer.Rel;
protected override void CreateHypermedia()
    Href = LinkTemplates.Beers.Beer.CreateLink(new { id = Id }).Href;

if (StyleId != null)
    Links.Add(LinkTemplates.BeerStyles.Style.CreateLink(new { id = StyleId }));
if (BreweryId != null)
    Links.Add(LinkTemplates.Breweries.Brewery.CreateLink(new { id = BreweryId }));


Sample controller action

public BreweryRepresentation Get(int id)
    var brewery = beerDbContext.Breweries.Find(id);

return new BreweryRepresentation
    Id = brewery.Id,
    Name = brewery.Name,
    Links =
        LinkTemplates.Breweries.AssociatedBeers.CreateLink(new { id })


Sample Project

To run the sample project, update the connection string in web.config, then create the database. When you hit an API for the first time, the database will be setup using DbUp.

You can use fiddler to explore the API. Make sure you put in an accept header of

. Try hitting
with that accept header, and see what happens


I have more credits to add, but this is the most obvious (as I based my Xml formatter off this project)

Release Notes

See Readme.txt at

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.