Support for hypermedia controls

Topics: Web Api
May 22, 2011 at 3:51 PM

In REST hypermedia controls should be first class citizens. Is there a "Link" class for that in the Web API to use it in the resources or headers?

 

Example:

    /// <summary>
    /// Hypermedia link
    /// </summary>
    public class Link
    {
        /// <summary>
        /// Link Relation, see e.g. http://www.iana.org/assignments/link-relations/link-relations.xhtml
        /// </summary>
        [XmlAttribute("Rel")]
        public string Rel { get; set; }

        /// <summary>
        /// Human readable title
        /// <remarks>Should be treated as xml content? e.g. <link rel="..." href="...">title</link></remarks>
        /// </summary>
        [XmlAttribute("Title")]
        public string Title { get; set; }

        /// <summary>
        /// URL
        /// </summary>
        [XmlAttribute("Href")]
        public string Href { get; set; }

        /// <summary>
        /// Mime (media) type
        /// </summary>
        [XmlAttribute("MimeType")]
        public string MimeType { get; set; }


        #region ctor

        ///<summary>
        /// default ctor
        ///</summary>
        public Link()
        {

        }

        /// <summary>
        /// Minimal ctor: url and relation
        /// </summary>
        /// <param name="href"></param>
        /// <param name="rel"></param>
        public Link(string href, string rel)
        {
            Href = href;
            Rel = rel;
        }

        /// <summary>
        /// ctor with mimetype
        /// </summary>
        /// <param name="href"></param>
        /// <param name="rel"></param>
        /// <param name="title"></param>
        public Link(string href, string rel, string title)
            : this(href, rel)
        {
            Title = title;
        }

        /// <summary>
        /// full ctor
        /// </summary>
        /// <param name="href"></param>
        /// <param name="rel"></param>
        /// <param name="mimetype"></param>
        /// <param name="title"></param>
        public Link(string href, string rel, string title, string mimetype)
            : this(href, rel, title)
        {
            MimeType = mimetype;
        }

        #endregion

    }

    /// <summary>
    /// A list of links
    /// </summary>
    public class Links : List<Link>
    {
        /// <summary>
        /// default ctos
        /// </summary>
        public Links()
        {

        }

        /// <summary>
        /// ctor with params 
        /// </summary>
        /// <param name="links"></param>
        public Links(params Link[] links)
        {
            AddRange(links);
        }

        /// <summary>
        /// ctor with IEnumerable
        /// </summary>
        /// <param name="links"></param>
        public Links(IEnumerable<Link> links)
        {
            AddRange(links);
        }

        public IEnumerable<Link> Find(string relationType)
        {
            var result = from l in this
                         where l.Rel == relationType
                         select l;

            return result;
        }
    }

 

 

May 23, 2011 at 2:10 AM

I have built a Link class in my REST Agent project.  It is still evolving but it might give you some ideas.  I haven't really used it yet on the server side, just client side stuff. 

May 24, 2011 at 9:41 PM

Thanks, i´ll check it out.

By the way: It would be very useful, if the Web API would provide some "Hypermedia control injection". This would make the aggregation of the above stated Links into the model classes obsolete. I´ve never tried it, but i think OpenRasta is doing something like this [1] . You can even choose, if the hypermedia controls are embedded into the HTTP header or into the entity body itself, which is quite nice.

[1] http://www.infoq.com/presentations/Building-a-RESTful-Architecture-with-OpenRasta   (around 00:35:00)

Coordinator
May 25, 2011 at 12:30 AM

Thanks Humbrie, I am familar with Seb's model as I was in the audience at this talk.

Our current thinking around hypermedia is we want to enable it and are deliberately supporting it in the design. We are not opinionated however on how you do it. Over time we may offer add-on solutions that you can use (but are not forced to use).

The way to do that injection in web api is through formatters or operation handlers. With formatters you do it for a specific media type. OR's support for custom formats is currently limited, but it does support XML as far I understand through XPATH.

With web api you can represent links any way you want to using any rendering format i.e. json, xml, or link headers and can inject them in several ways.

1. You can write formatters that support embedding links. Those links can be embedded as link headers or within the response body. Today getting access to the response in the formatter to modify the headers isn't easy but we will be fixing that.2

2. You can write an operation handler that takes the return value of the operation and adds links to it before it hits the formatter.

 

 

Coordinator
May 25, 2011 at 12:36 AM
Edited May 25, 2011 at 12:44 AM

Humbrie

In terms of the link class, for the same reason I cited above we do not have one. There are variant opinions on how to represent links or even if you have a link element itself. The link structure itself varies from the most simple link with uri and href to folks that add additional control information up front as in atom links and the list you have above. Not to mention there is the forms approach to linking as I mentioned here

Some folks don't use a link element at all as Mike Amundsen has shown using <Query> as a hypermedia control.

With web api were making it easy to use whichever strategy you prefer without telling you which one to use. 

May 25, 2011 at 7:33 AM

Thanks for the detailed information. I´ve been playing around with the current bits and i like all the enhancements you made so far since the "rest starter kit" days.

Jakob