Getting Started With The Vimeo API in C#

Share |
by Rob 6. August 2010 16:58

In my last post I showed you how to get started with using Google’s YouTube API to return a user’s favourites feed and get information for a single video. In this article I continue the theme by showing you how to use the Vimeo API to search and retrieve a collection of videos and then retrieve and show one video.

You can download the source files for this solution here. UPDATE: The solution is in VS2010, on request I have made a VS2005 version that can be downloaded here.

UPDATE: Please ensure you have the latest version of Flash player installed otherwise the videos might not show! (I just tried in Internet Explorer and had to update).

Vimeo is a great video repository and is home to lots of drifting videos. Because of the prevalence of drifting videos I wrote a wrapper for the Vimeo API in C# so I could use it on JDMLegion.com.

Before reading any further I suggest you have a look through Vimeo’s API guide’s, both simple and advanced, by visiting www.vimeo.com/api . If you are not familiar with OAuth or OEmbed, it would be worth having a quick skim through the following 2 pages as well - www.vimeo.com/api/docs/oauth and www.vimeo.com/api/docs/oembed.

The Vimeo API can output both JSON and XML, but I will be using only XML for this solution.

Vimeo Consumer Key And Consumer Secret

In order for OAuth requests to work for the advanced API you will need to register with Vimeo and obtain a consumer key and consumer secret – A little like the developer key we had to request from Google for the YouTube API to work in my previous post. You can get a consumer key and consumer secret at www.vimeo.com/api/applications/new.

The Code

As with my YouTube solution, I have separated this solution into 3 projects - the web application and 2 class libraries. There is some extra code in this solution in the VimeoAPI class that serves as interfaces for methods that the Vimeo API offers but we are not using in this example. Whilst these are untested and for this solution are not necessary, I have decided to add them to save you some work should you want to use any of these methods in the future.

We’ll start with our BusinessObject class library.

VideoExtracted.cs

namespace BusinessObject
{
    public class VideoExtracted
    {
        public string VideoId { get; set; }
        public string Title { get; set; }
        public string Thumbnail { get; set; }
        public string Description { get; set; }
    }
}

This is a wrapper for the video information we want returned from the Vimeo API.

OEmbed.cs

using System;
using System.Xml.Serialization;

namespace BusinessObject
{
    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    [XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "oembed")]
    public class OEmbed
    {
        public string type { get; set; }
        public string version { get; set; }
        public string provider_name { get; set; }
        public string provider_url { get; set; }
        public string title { get; set; }
        public string author_name { get; set; }
        public string author_url { get; set; }
        public string is_plus { get; set; }
        public string html { get; set; }
        public string width { get; set; }
        public string height { get; set; }
        public string duration { get; set; }
        public string thumbnail_url { get; set; }
        public string thumbnail_width { get; set; }
        public string thumbnail_height { get; set; }
        public string video_id { get; set; }
    }
}

This is a wrapper for our OEmbed request.

VimeoVideoWrapper.cs

using System;
using System.Xml.Serialization;

namespace BusinessObject
{
    [SerializableAttribute]
    [XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "videos")]
    public class VimeoVideoWrapper
    {
        [XmlElementAttribute("video")]
        public VimeoVideo[] Videos { get; set;}
    }

    [SerializableAttribute]
    public class VimeoVideo
    {
        public string id { get; set; }
        public string title { get; set; }
        public string description { get; set; }
        public string url { get; set; }
        public string upload_date { get; set; }
        public string thumbnail_small { get; set; }
        public string thumbnail_medium { get; set; }
        public string thumbnail_large { get; set; }
        public string user_name { get; set; }
        public string user_url { get; set; }
        public string user_portrait_small { get; set; }
        public string user_portrait_medium { get; set; }
        public string user_portrait_large { get; set; }
        public string user_portrait_huge { get; set; }
        public string stats_number_of_likes { get; set; }
        public string stats_number_of_plays { get; set; }
        public string stats_number_of_comments { get; set; }
        public string duration { get; set; }
        public string width { get; set; }
        public string height { get; set; }
        public string tags { get; set; }
    }
}

This is a wrapper for our Vimeo video request.

VimeoVideoThumbnailResponse.cs

using System;
using System.Xml.Serialization;

namespace BusinessObject
{
    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    [XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "rsp")]
    public class VimeoVideoThumbnailsResponse
    {
        [XmlElementAttribute("thumbnails", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public VimeoVideoThumbnailsWrapper thumbnails { get; set; }
        [XmlAttributeAttribute()]
        public string generated_in { get; set; }
        [XmlAttributeAttribute()]
        public string stat { get; set; }
    }

    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    public class VimeoVideoThumbnailsWrapper
    {
        [XmlElementAttribute("thumbnail", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public VimeoVideoThumbnailWrapper[] thumbnail { get; set; }
    }

    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    public class VimeoVideoThumbnailWrapper
    {
        [XmlAttributeAttribute()]
        public string height { get; set; }
        [XmlAttributeAttribute()]
        public string width { get; set; }
        [XmlText()]
        public string thumbnail { get; set; }
    }
}

A wrapper to use when requesting Vimeo video thumbnails.

VimeoSearchResponse.cs

using System;
using System.Xml.Serialization;

namespace BusinessObject
{
    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    [XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "rsp")]
    public partial class VimeoSearchResponse
    {
        [XmlElementAttribute("videos", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public SearchResponseVideosWrapper videos { get; set; }
        [XmlAttributeAttribute()]
        public string generated_in { get; set; }
        [XmlAttributeAttribute()]
        public string stat { get; set; }
    }

    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    public partial class SearchResponseVideosWrapper
    {
        [XmlElementAttribute("video", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public SearchResponseVideosWrapperVideo[] video { get; set; }
        [XmlAttributeAttribute()]
        public string on_this_page { get; set; }
        [XmlAttributeAttribute()]
        public string page { get; set; }
        [XmlAttributeAttribute()]
        public string perpage { get; set; }
        [XmlAttributeAttribute()]
        public string total { get; set; }
    }

    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    public partial class SearchResponseVideosWrapperVideo
    {
        [XmlAttributeAttribute()]
        public string embed_privacy { get; set; }
        [XmlAttributeAttribute()]
        public string id { get; set; }
        [XmlAttributeAttribute()]
        public string is_hd { get; set; }
        [XmlAttributeAttribute()]
        public string owner { get; set; }
        [XmlAttributeAttribute()]
        public string privacy { get; set; }
        [XmlAttributeAttribute()]
        public string title { get; set; }
        [XmlAttributeAttribute()]
        public string upload_date { get; set; }
    }

    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    [XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class VimeoSearchResponses
    {
        [XmlElementAttribute("rsp")]
        public VimeoSearchResponse[] items { get; set; }
    }
}

A wrapper to use when making search requests.

VimeoErrorResponse.cs

using System;
using System.Xml.Serialization;

namespace BusinessObject
{
    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    [XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "rsp")]
    public class VimeoErrorResponse
    {
        [XmlElementAttribute("err", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public VimeoErrorWrapper error { get; set; }
        [XmlAttributeAttribute()]
        public string generated_in { get; set; }
        [XmlAttributeAttribute()]
        public string stat { get; set; }
    }

    [SerializableAttribute]
    [XmlTypeAttribute(AnonymousType = true)]
    public class VimeoErrorWrapper
    {
        [XmlAttributeAttribute()]
        public string code { get; set; }
        [XmlAttributeAttribute()]
        public string msg { get; set; }
    }
}

A wrapper for any error responses.

Now we need to create our Common class library. As in the YouTube project we have a GlobalConstants class.

GlobalConstants.cs

using System;
using System.Text;

namespace Common
{
    /// <summary>
    /// Global constants for the solution
    /// </summary>
    public class GlobalConstants
    {
        #region VimeoAPI
        /// <summary>
        /// Constants required to use the Vimeo API
        /// </summary>
        public class VimeoAPI
        {
            /// <summary>
            /// the vimeo api consumer key - your consumer key
            /// </summary>
            public const string ConsumerKey = "your consumer key";
            /// <summary>
            /// the vimeo api consumer secret - your consumer secret
            /// </summary>
            public const string ConsumerSecret = "your consumer secret";
            /// <summary>
            /// http://vimeo.com/api/rest/v2/
            /// </summary>
            public const string StandardAdvancedApiUrl = "http://vimeo.com/api/rest/v2";
            /// <summary>
            /// StandardAdvancedApiUrl + ?method=vimeo.videos.search&query=
            /// </summary>
            public const string SearchUrl = StandardAdvancedApiUrl 
                + "?method=vimeo.videos.search&per_page=15&query=";
            /// <summary>
            /// StandardAdvancedApiUrl + ?method=vimeo.videos.getThumbnailUrls&video_id=
            /// </summary>
            public const string GetVideoThumbnailsUrl = StandardAdvancedApiUrl 
                + "?method=vimeo.videos.getThumbnailUrls&video_id=";
            /// <summary>
            /// create all required Oauth parameters
            /// </summary>
            public static string OAuthParameters = BuildOAuthParameters();

            /// <summary>
            /// http://vimeo.com/api/oembed.xml?url=http%3A//vimeo.com/
            /// </summary>
            public const string OembedRequestUrlFormat = 
                "http://vimeo.com/api/oembed.xml?url=http%3A//vimeo.com/";
            /// <summary>
            /// http://vimeo.com/api/v2/
            /// </summary>
            /// <see cref="http://www.vimeo.com/api/docs/simple-api"/>
            public const string BaseVimeoUrl = "http://vimeo.com/api/v2/";
            /// <summary>
            /// http://vimeo.com/api/v2/username/request.output
            /// </summary>
            /// <see cref="http://www.vimeo.com/api/docs/simple-api"/>
            public const string UserRequestUrlFormat = BaseVimeoUrl + "{0}/{1}.{2}";
            /// <summary>
            /// http://vimeo.com/api/v2/video/video_id.output
            /// </summary>
            /// /// <see cref="http://www.vimeo.com/api/docs/simple-api"/>
            public const string VideoRequestUrlFormat = BaseVimeoUrl + "video/{0}.{1}";
            /// <summary>
            /// http://vimeo.com/api/v2/activity/username/request.output
            /// </summary>
            /// /// <see cref="http://www.vimeo.com/api/docs/simple-api"/>
            public const string ActivityRequestUrlFormat = BaseVimeoUrl 
                + "activity/{0}/{1}.{2}";
            /// <summary>
            /// http://vimeo.com/api/v2/group/groupname/request.output
            /// </summary>
            /// /// <see cref="http://www.vimeo.com/api/docs/simple-api"/>
            public const string GroupRequestUrlFormat = BaseVimeoUrl + "group/{0}/{1}.{2}";
            /// <summary>
            /// http://vimeo.com/api/v2/channel/channelname/request.output
            /// </summary>
            /// /// <see cref="http://www.vimeo.com/api/docs/simple-api"/>
            public const string ChannelRequestUrlFormat = BaseVimeoUrl 
                + "channel/{0}/{1}.{2}";
            /// <summary>
            /// http://vimeo.com/api/v2/album/album_id/request.output
            /// </summary>
            /// /// <see cref="http://www.vimeo.com/api/docs/simple-api"/>
            public const string AlbumRequestUrlFormat = BaseVimeoUrl + "album/{0}/{1}.{2}";
            /// <summary>
            /// Vimeo player width
            /// </summary>
            public const string VimeoPlayerWidth = "550";
            /// <summary>
            /// Vimeo player height
            /// </summary>
            public const string VimeoPlayerHeight = "425";

            /// <summary>
            /// Builds the Oauth parameters.
            /// </summary>
            /// <returns></returns>
            protected static string BuildOAuthParameters()
            {
                var sb = new StringBuilder();

                sb.Append("&oauth_consumer_key=");
                sb.Append(ConsumerKey);
                sb.Append("&oauth_nonce=");
                sb.Append(Guid.NewGuid());
                sb.Append("&oauth_signature_method=HMAC-SHA1");
                sb.Append("&oauth_timestamp=");

                TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));

                sb.Append(ts.TotalSeconds);
                sb.Append("&oauth_version=1.0");

                return sb.ToString();
            }
        }
        #endregion

        #region Links
        /// <summary>
        /// Page links
        /// </summary>
        public class Links
        {
            /// <summary>
            /// Default.aspx
            /// </summary>
            public const string Default = "/Default.aspx";
            /// <summary>
            /// ViewVideo.aspx?vid=
            /// </summary>
            public const string ViewVideo = "/ViewVideo.aspx?" + Querystring.Video + "=";
        }
        #endregion

        #region Querystring
        /// <summary>
        /// Querystring identifiers
        /// </summary>
        public class Querystring
        {
            /// <summary>
            /// vid
            /// </summary>
            public const string Video = "vid";
        }
        #endregion

        #region ErrorMessages
        /// <summary>
        /// Querystring identifiers
        /// </summary>
        public class ErrorMessages
        {
            /// <summary>
            /// Sorry, Vimeo's search service is temporarily unavailable. 
            /// Please try again in a few minutes.
            /// </summary>
            public const string SearchServiceUnavailable 
                = "Sorry, Vimeo's search service is temporarily unavailable. "
                +"Please try again in a few minutes.";
            /// <summary>
            /// Sorry, there was an error with your search. If the problem persists please #
            /// contact us and let us know about the issue, thanks.
            /// </summary>
            public const string SearchError 
                = "Sorry, there was an error with your search. If the problem persists please"
                + " contact us and let us know about the issue, thanks.";
            /// <summary>
            /// Sorry, your query returned no results
            /// </summary>
            public const string NoSearchResults = "Sorry, your query returned no results";
        }
        #endregion
    }
}

 

You will need to change the consumer key and consumer secrets field in this class to the ones you received when you signed up to Vimeo and registered your application.

OAuthBase.cs

using System;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Text;
using System.Web;
using BusinessObject.Enums;

namespace Common
{
    public class OAuthBase
    {
        /// <summary>
        /// Provides an internal structure to sort the query parameter
        /// </summary>
        protected class QueryParameter
        {
            public QueryParameter(string name, string value)
            {
                Name = name;
                Value = value;
            }

            public string Name { get; private set; }
            public string Value { get; private set; }
        }

        /// <summary>
        /// Comparer class used to perform the sorting of the query parameters
        /// </summary>
        protected class QueryParameterComparer : IComparer<QueryParameter>
        {
            public int Compare(QueryParameter x, QueryParameter y)
            {
                return x.Name == y.Name 
                    ? string.Compare(x.Value, y.Value) 
                    : string.Compare(x.Name, y.Name);
            }
        }

        protected const string OAuthVersion = "1.0";
        protected const string OAuthParameterPrefix = "oauth_";

        // List of know and used oauth parameters' names
        protected const string OAuthConsumerKeyKey = "oauth_consumer_key";
        protected const string OAuthCallbackKey = "oauth_callback";
        protected const string OAuthVersionKey = "oauth_version";
        protected const string OAuthSignatureMethodKey = "oauth_signature_method";
        protected const string OAuthSignatureKey = "oauth_signature";
        protected const string OAuthTimestampKey = "oauth_timestamp";
        protected const string OAuthNonceKey = "oauth_nonce";
        protected const string OAuthTokenKey = "oauth_token";
        protected const string OAuthTokenSecretKey = "oauth_token_secret";

        protected const string HMACSHA1SignatureType = "HMAC-SHA1";
        protected const string PlainTextSignatureType = "PLAINTEXT";
        protected const string RSASHA1SignatureType = "RSA-SHA1";

        protected Random random = new Random();

        protected string unreservedChars = 
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";

        /// <summary>
        /// Helper function to compute a hash value
        /// </summary>
        /// <param name="hashAlgorithm">The hashing algoirhtm used. If that algorithm needs 
        /// some initialization, like HMAC and its derivatives, they should be initialized 
        /// prior to passing it to this function</param>
        /// <param name="data">The data to hash</param>
        /// <returns>a Base64 string of the hash value</returns>
        private static string ComputeHash(HashAlgorithm hashAlgorithm, string data)
        {
            if (hashAlgorithm == null)
                throw new ArgumentNullException("hashAlgorithm");

            if (string.IsNullOrEmpty(data))
                throw new ArgumentNullException("data");

            byte[] dataBuffer = Encoding.ASCII.GetBytes(data);
            byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer);

            return Convert.ToBase64String(hashBytes);
        }

        /// <summary>
        /// Internal function to cut out all non oauth query string parameters 
        /// (all parameters not begining with "oauth_")
        /// </summary>
        /// <param name="parameters">The query string part of the Url</param>
        /// <returns>A list of QueryParameter each containing the parameter name and 
        /// value</returns>
        private static List<QueryParameter> GetQueryParameters(string parameters)
        {
            if (parameters.StartsWith("?"))
                parameters = parameters.Remove(0, 1);

            var result = new List<QueryParameter>();

            if (!string.IsNullOrEmpty(parameters))
            {
                string[] p = parameters.Split('&');
                foreach (string s in p)
                {
                    if (string.IsNullOrEmpty(s) || s.StartsWith(OAuthParameterPrefix)) 
                        continue;

                    if (s.IndexOf('=') > -1)
                    {
                        string[] temp = s.Split('=');
                        result.Add(new QueryParameter(temp[0], temp[1]));
                    }
                    else
                        result.Add(new QueryParameter(s, string.Empty));
                }
            }

            return result;
        }

        /// <summary>
        /// This is a different Url Encode implementation since the default 
        /// .NET one outputs the percent encoding in lower case.
        /// While this is not a problem with the percent encoding spec, 
        /// it is used in upper case throughout OAuth
        /// </summary>
        /// <param name="value">The value to Url encode</param>
        /// <returns>Returns a Url encoded string</returns>
        protected string UrlEncode(string value)
        {
            var result = new StringBuilder();

            foreach (char symbol in value)
            {
                if (unreservedChars.IndexOf(symbol) != -1)
                    result.Append(symbol);
                else
                    result.Append('%' + String.Format("{0:X2}", (int)symbol));
            }

            return result.ToString();
        }

        /// <summary>
        /// Normalizes the request parameters according to the spec
        /// </summary>
        /// <param name="parameters">The list of parameters already sorted</param>
        /// <returns>a string representing the normalized parameters</returns>
        protected string NormalizeRequestParameters(IList<QueryParameter> parameters)
        {
            var sb = new StringBuilder();
            QueryParameter p;
            for (int i = 0; i < parameters.Count; i++)
            {
                p = parameters[i];
                sb.AppendFormat("{0}={1}", p.Name, p.Value);

                if (i < parameters.Count - 1)
                    sb.Append("&");
            }

            return sb.ToString();
        }

        /// <summary>
        /// Generate the signature base that is used to produce the signature
        /// </summary>
        /// <param name="url">The full url that needs to be signed including 
        /// its non OAuth url parameters</param>
        /// <param name="consumerKey">The consumer key</param>        
        /// <param name="token">The token, if available. If not available 
        /// pass null or an empty string</param>
        /// <param name="tokenSecret">The token secret, if available. If not 
        /// available pass null or an empty string</param>
        /// <param name="httpMethod">The http method used. Must be a valid HTTP 
        /// method verb (POST,GET,PUT, etc)</param>
        /// <param name="signatureType">The signature type. To use the default 
        /// values use <see cref="OAuthBase.OAuthSignatureType">
        /// OAuthBase.OAuthSignatureType</see>.
        /// </param>
        /// <returns>The signature base</returns>
        public string GenerateSignatureBase(Uri url, string consumerKey, string token, 
            string tokenSecret, string httpMethod, string timeStamp, string nonce, 
            string signatureType, out string normalizedUrl, 
            out string normalizedRequestParameters)
        {
            if (token == null)
                token = string.Empty;

            //if (tokenSecret == null)
            //    tokenSecret = string.Empty;

            if (string.IsNullOrEmpty(consumerKey))
                throw new ArgumentNullException("consumerKey");

            if (string.IsNullOrEmpty(httpMethod))
                throw new ArgumentNullException("httpMethod");

            if (string.IsNullOrEmpty(signatureType))
                throw new ArgumentNullException("signatureType");

            normalizedUrl = null;
            normalizedRequestParameters = null;

            List<QueryParameter> parameters = GetQueryParameters(url.Query);
            parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion));
            parameters.Add(new QueryParameter(OAuthNonceKey, nonce));
            parameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp));
            parameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType));
            parameters.Add(new QueryParameter(OAuthConsumerKeyKey, consumerKey));

            if (!string.IsNullOrEmpty(token))
                parameters.Add(new QueryParameter(OAuthTokenKey, token));

            parameters.Sort(new QueryParameterComparer());

            normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);

            if (!((url.Scheme == "http" && url.Port == 80) || 
                (url.Scheme == "https" && url.Port == 443)))
                normalizedUrl += ":" + url.Port;

            normalizedUrl += url.AbsolutePath;
            normalizedRequestParameters = NormalizeRequestParameters(parameters);

            var signatureBase = new StringBuilder();
            signatureBase.AppendFormat("{0}&", httpMethod.ToUpper());
            signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl));
            signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));

            return signatureBase.ToString();
        }

        /// <summary>
        /// Generate the signature value based on the given signature base
        /// and hash algorithm
        /// </summary>
        /// <param name="signatureBase">The signature based as produced 
        /// by the GenerateSignatureBase method or by any other means</param>
        /// <param name="hash">The hash algorithm used to perform the hashing. 
        /// If the hashing algorithm requires initialization or a key it 
        /// should be set prior to calling this method</param>
        /// <returns>A base64 string of the hash value</returns>
        public string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash)
        {
            return ComputeHash(hash, signatureBase);
        }

        /// <summary>
        /// Generates a signature using the HMAC-SHA1 algorithm
        /// </summary>        
        /// <param name="url">The full url that needs to be signed including its 
        /// non OAuth url parameters</param>
        /// <param name="consumerKey">The consumer key</param>
        /// <param name="consumerSecret">The consumer seceret</param>
        /// <param name="token">The token, if available. If not available pass 
        /// null or an empty string</param>
        /// <param name="tokenSecret">The token secret, if available. If not 
        /// available pass null or an empty string</param>
        /// <param name="httpMethod">The http method used. Must be a valid HTTP 
        /// method verb (POST,GET,PUT, etc)</param>
        /// <returns>A base64 string of the hash value</returns>
        public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, 
            string token, string tokenSecret, string httpMethod, string timeStamp, 
            string nonce, out string normalizedUrl, out string normalizedRequestParameters)
        {
            return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, 
                httpMethod, timeStamp, nonce, OAuthSignatureType.HMACSHA1, out normalizedUrl, 
                out normalizedRequestParameters);
        }

        /// <summary>
        /// Generates a signature using the specified signatureType 
        /// </summary>        
        /// <param name="url">The full url that needs to be signed including 
        /// its non OAuth url parameters</param>
        /// <param name="consumerKey">The consumer key</param>
        /// <param name="consumerSecret">The consumer seceret</param>
        /// <param name="token">The token, if available. If not available pass 
        /// null or an empty string</param>
        /// <param name="tokenSecret">The token secret, if available. If not 
        /// available pass null or an empty string</param>
        /// <param name="httpMethod">The http method used. Must be a valid HTTP 
        /// method verb (POST,GET,PUT, etc)</param>
        /// <param name="signatureType">The type of signature to use</param>
        /// <returns>A base64 string of the hash value</returns>
        public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, 
            string token, string tokenSecret, string httpMethod, string timeStamp, 
            string nonce, OAuthSignatureType signatureType, out string normalizedUrl, 
            out string normalizedRequestParameters)
        {
            normalizedUrl = null;
            normalizedRequestParameters = null;

            switch (signatureType)
            {
                case OAuthSignatureType.PLAINTEXT:
                    return HttpUtility.UrlEncode(
                        string.Format("{0}&{1}", consumerSecret, tokenSecret));
                case OAuthSignatureType.HMACSHA1:
                    string signatureBase = GenerateSignatureBase(url, consumerKey, 
                        token, tokenSecret, 
                        httpMethod, timeStamp, nonce, HMACSHA1SignatureType,
                        out normalizedUrl, out normalizedRequestParameters);

                    var hmacsha1 = new HMACSHA1
                                       {
                                           Key = Encoding.ASCII.GetBytes(
                                                string.Format("{0}&{1}", 
                                                UrlEncode(consumerSecret),
                                                string.IsNullOrEmpty(tokenSecret) 
                                                    ? "" 
                                                    : UrlEncode(tokenSecret)))
                                       };

                    return GenerateSignatureUsingHash(signatureBase, hmacsha1);
                case OAuthSignatureType.RSASHA1:
                    throw new NotImplementedException();
                default:
                    throw new ArgumentException("Unknown signature type", "signatureType");
            }
        }

        /// <summary>
        /// Generate the timestamp for the signature        
        /// </summary>
        /// <returns></returns>
        public virtual string GenerateTimeStamp()
        {
            // Default implementation of UNIX time of the current UTC time
            TimeSpan ts = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0));
            string timeStamp = ts.TotalSeconds.ToString();
            timeStamp = timeStamp.Substring(0, timeStamp.IndexOf("."));
            return timeStamp;
        }

        /// <summary>
        /// Generate a nonce (childish giggle)
        /// </summary>
        /// <returns></returns>
        public virtual string GenerateNonce()
        {
            // Just a simple implementation of a random number between 123400 and 9999999
            return random.Next(123400, 9999999).ToString();
        }
    }
}

 

This class contains all the methods required for making requests with OAuth.

VimeoAPI.cs

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.Serialization;
using BusinessObject;
using BusinessObject.Enums;

namespace Common
{
    public class VimeoAPI
    {
        /// <summary>
        /// Executes an HTTP GET command and retrieves the vimeoApiOutputFormatType.        
        /// </summary>
        /// <param name="url">The URL to perform the GET operation</param>
        /// <param name="userName">The username to use with the request</param>
        /// <param name="password">The password to use with the request</param>
        /// <returns>The response of the request, or null if we got 404 or nothing.</returns>
        protected static string ExecuteGetCommand(string url, string userName, 
            string password)
        {
            using (var wc = new WebClient())
            {
                if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
                    wc.Credentials = new NetworkCredential(userName, password);

                try
                {
                    using (Stream stream = wc.OpenRead(url))
                    {
                        using (var reader = new StreamReader(stream))
                        {
                            return reader.ReadToEnd();
                        }
                    }
                }
                catch (WebException ex)
                {
                    // Handle HTTP 404 errors gracefully and return a null string 
                    // to indicate there is no content.
                    if (ex.Response is HttpWebResponse)
                        if ((ex.Response as HttpWebResponse).StatusCode 
                            == HttpStatusCode.NotFound)
                            return null;

                    throw;
                }
            }
        }

        /// <summary>
        /// Builds the OAuth API request URL.
        /// </summary>
        /// <param name="url">The URL.</param>
        /// <returns></returns>
        protected static string BuildOAuthApiRequestUrl(string url)
        {
            var oAuth = new OAuthBase();
            string nonce = oAuth.GenerateNonce();
            string timeStamp = oAuth.GenerateTimeStamp();

            string normalizedUrl;
            string normalizedRequestParameters;

            var uri = new Uri(url);

            string sig = oAuth.GenerateSignature(uri, GlobalConstants.VimeoAPI.ConsumerKey, 
                    GlobalConstants.VimeoAPI.ConsumerSecret, 
                    string.Empty, string.Empty, "GET", timeStamp, nonce, 
                    OAuthSignatureType.HMACSHA1, 
                    out normalizedUrl, out normalizedRequestParameters);
            
            sig = HttpUtility.UrlEncode(sig);

            var sb = new StringBuilder(uri.ToString());
            sb.AppendFormat("&oauth_consumer_key={0}&", GlobalConstants.VimeoAPI.ConsumerKey);
            sb.AppendFormat("oauth_nonce={0}&", nonce);
            sb.AppendFormat("oauth_timestamp={0}&", timeStamp);
            sb.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
            sb.AppendFormat("oauth_version={0}&", "1.0");
            sb.AppendFormat("oauth_signature={0}", sig);
            
            return sb.ToString();
        }

        /// <summary>
        /// XML requests
        /// </summary>
        public class RequestInXML
        {
            /// <summary>
            /// User requests
            /// </summary>
            public class User
            {
                /// <summary>
                /// Gets the albums user has created.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetAlbumsUserHasCreated(string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.albums, username);
                }

                /// <summary>
                /// Gets the videos user has appeared in and created.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetVideosUserHasAppearedInAndCreated
                    (string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.all_videos, username);
                }

                /// <summary>
                /// Gets the videos user has appeared in.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetVideosUserHasAppearedIn(string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.appears_in, username);
                }

                /// <summary>
                /// Gets the channels user has created and is subscribed to.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetChannelsUserHasCreatedAndIsSubscribedTo
                    (string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.channels, username);
                }

                /// <summary>
                /// Gets the videos users contacts like.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetVideosUsersContactsLike(string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.contacts_like, username);
                }

                /// <summary>
                /// Gets the videos users contacts created.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetVideosUsersContactsCreated(string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.contacts_videos, 
                        username);
                }

                /// <summary>
                /// Gets the groups user has created and joined.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetGroupsUserHasCreatedAndJoined(string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.groups, username);
                }

                /// <summary>
                /// Gets the user info.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetUserInfo(string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.info, username);
                }

                /// <summary>
                /// Gets the videos user likes.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetVideosUserLikes(string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.likes, username);
                }

                /// <summary>
                /// Gets the videos user is subscribed to.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetVideosUserIsSubscribedTo(string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.subscriptions, username);
                }

                /// <summary>
                /// Gets the videos created by user.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetVideosCreatedByUser(string username)
                {
                    return DoUserRequestAsXML(VimeoApiUserRequestType.videos, username);
                }
            }

            /// <summary>
            /// Video requests
            /// </summary>
            public class Video
            {
                /// <summary>
                /// Gets the video.
                /// </summary>
                /// <param name="videoId">The video id.</param>
                /// <returns></returns>
                public static XmlDocument GetVideo(string videoId)
                {
                    return DoVideoRequestAsXML(videoId);
                }
            }

            /// <summary>
            /// Activity requests
            /// </summary>
            public class Activity
            {
                /// <summary>
                /// Gets the activity by the users contacts.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetActivityByTheUsersContacts(string username)
                {
                    return DoActivityRequestAsXML(VimeoApiActivityRequestType.contacts_did, 
                        username);
                }

                /// <summary>
                /// Gets the activity by everyone.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetActivityByEveryone(string username)
                {
                    return DoActivityRequestAsXML(VimeoApiActivityRequestType.everyone_did, 
                        username);
                }

                /// <summary>
                /// Gets the activity on the users contacts.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetActivityOnTheUsersContacts(string username)
                {
                    return DoActivityRequestAsXML(VimeoApiActivityRequestType.happened_to_contacts, username);
                }

                /// <summary>
                /// Gets the activity on the user.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetActivityOnTheUser(string username)
                {
                    return DoActivityRequestAsXML
                        (VimeoApiActivityRequestType.happened_to_user, username);
                }

                /// <summary>
                /// Gets the activity by the user.
                /// </summary>
                /// <returns></returns>
                public static XmlDocument GetActivityByTheUser(string username)
                {
                    return DoActivityRequestAsXML
                        (VimeoApiActivityRequestType.user_did, username);
                }
            }

            /// <summary>
            /// Album requests
            /// </summary>
            public class Album
            {
                /// <summary>
                /// Gets the album info.
                /// </summary>
                /// <param name="albumId">The album id.</param>
                /// <returns></returns>
                public static XmlDocument GetAlbumInfo(string albumId)
                {
                    return DoAlbumRequestAsXML(VimeoApiAlbumRequestType.info, albumId);
                }

                /// <summary>
                /// Gets the videos in album.
                /// </summary>
                /// <param name="albumId">The album id.</param>
                /// <returns></returns>
                public static XmlDocument GetVideosInAlbum(string albumId)
                {
                    return DoAlbumRequestAsXML(VimeoApiAlbumRequestType.videos, albumId);
                }
            }

            /// <summary>
            /// Channel requests
            /// </summary>
            public class Channel
            {
                /// <summary>
                /// Gets the channel info.
                /// </summary>
                /// <param name="channelName">Name of the channel.</param>
                /// <returns></returns>
                public static XmlDocument GetChannelInfo(string channelName)
                {
                    return DoChannelRequestAsXML(VimeoApiChannelRequestType.info, 
                        channelName);
                }

                /// <summary>
                /// Gets the videos in channel.
                /// </summary>
                /// <param name="channelName">Name of the channel.</param>
                /// <returns></returns>
                public static XmlDocument GetVideosInChannel(string channelName)
                {
                    return DoChannelRequestAsXML(VimeoApiChannelRequestType.videos, 
                        channelName);
                }
            }

            /// <summary>
            /// Group requests
            /// </summary>
            public class Group
            {
                /// <summary>
                /// Gets the group info.
                /// </summary>
                /// <param name="groupName">Name of the group.</param>
                /// <returns></returns>
                public static XmlDocument GetGroupInfo(string groupName)
                {
                    return DoGroupRequestAsXML(VimeoApiGroupRequestType.info, groupName);
                }

                /// <summary>
                /// Gets the users in group.
                /// </summary>
                /// <param name="groupName">Name of the group.</param>
                /// <returns></returns>
                public static XmlDocument GetUsersInGroup(string groupName)
                {
                    return DoGroupRequestAsXML(VimeoApiGroupRequestType.users, groupName);
                }

                /// <summary>
                /// Gets the videos in group.
                /// </summary>
                /// <param name="groupName">Name of the group.</param>
                /// <returns></returns>
                public static XmlDocument GetVideosInGroup(string groupName)
                {
                    return DoGroupRequestAsXML(VimeoApiGroupRequestType.videos, groupName);
                }
            }
        }

        #region Methods to perform the requests for each Vimeo request type
        /// <summary>
        /// Does the user request.
        /// </summary>
        /// <param name="vimeoApiOutputFormatType">Type of the vimeo API output format.</param>
        /// <param name="vimeoApiUserRequestType">Type of the vimeo API user request.</param>
        /// <param name="username">The username.</param>
        /// <returns></returns>
        protected static string DoUserRequest
            (VimeoApiOutputFormatType vimeoApiOutputFormatType, 
            VimeoApiUserRequestType vimeoApiUserRequestType, string username)
        {
            string url = string.Format(GlobalConstants.VimeoAPI.UserRequestUrlFormat, 
                username, GetVimeoApiUserRequestTypeString(vimeoApiUserRequestType), 
                GetVimeoApiOutputFormatTypeString(vimeoApiOutputFormatType));
            return ExecuteGetCommand(url, null, null);
        }

        /// <summary>
        /// Does the user request as XML.
        /// </summary>
        /// <param name="vimeoApiUserRequestType">Type of the vimeo API user request.</param>
        /// <param name="username">The username.</param>
        /// <returns></returns>
        protected static XmlDocument DoUserRequestAsXML
            (VimeoApiUserRequestType vimeoApiUserRequestType, string username)
        {
            string output = DoUserRequest(VimeoApiOutputFormatType.XML, 
                vimeoApiUserRequestType, username);
            if (!string.IsNullOrEmpty(output))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(output);

                return xmlDocument;
            }

            return null;
        }

        /// <summary>
        /// Does the video request.
        /// </summary>
        /// <param name="vimeoApiOutputFormatType">Type of the vimeo API output format.</param>
        /// <param name="videoId">The video id.</param>
        /// <returns></returns>
        protected static string DoVideoRequest
            (VimeoApiOutputFormatType vimeoApiOutputFormatType, string videoId)
        {
            string url = string.Format(GlobalConstants.VimeoAPI.VideoRequestUrlFormat, 
                videoId, 
                GetVimeoApiOutputFormatTypeString(vimeoApiOutputFormatType));
            return ExecuteGetCommand(url, null, null);
        }

        /// <summary>
        /// Does the video request as XML.
        /// </summary>
        /// <param name="videoId">The video id.</param>
        /// <returns></returns>
        protected static XmlDocument DoVideoRequestAsXML(string videoId)
        {
            string output = DoVideoRequest(VimeoApiOutputFormatType.XML, videoId);
            if (!string.IsNullOrEmpty(output))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(output);

                return xmlDocument;
            }

            return null;
        }

        /// <summary>
        /// Does the oembed request.
        /// </summary>
        /// <param name="vimeoApiOutputFormatType">Type of the vimeo API output format.</param>
        /// <param name="videoId">The video id.</param>
        /// <returns></returns>
        protected static string DoOembedRequest
            (VimeoApiOutputFormatType vimeoApiOutputFormatType, string videoId)
        {
            string url = GlobalConstants.VimeoAPI.OembedRequestUrlFormat + videoId
                         + "?maxwidth=" + GlobalConstants.VimeoAPI.VimeoPlayerWidth
                         + "&maxheight=" + GlobalConstants.VimeoAPI.VimeoPlayerHeight;

            return ExecuteGetCommand(url, null, null);
        }

        /// <summary>
        /// Does the oembed request as XML.
        /// </summary>
        /// <param name="videoId">The video id.</param>
        /// <returns></returns>
        protected static XmlDocument DoOembedRequestAsXML(string videoId)
        {
            string output = DoOembedRequest(VimeoApiOutputFormatType.XML, videoId);
            if (!string.IsNullOrEmpty(output))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(output);

                return xmlDocument;
            }

            return null;
        }

        /// <summary>
        /// Does a search request.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <returns>XmlDocument</returns>
        protected static XmlDocument DoSearchRequest(string query)
        {
            string output = ExecuteGetCommand
                (BuildOAuthApiRequestUrl(GlobalConstants.VimeoAPI.SearchUrl + query), 
                null, null);

            if (!string.IsNullOrEmpty(output))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(output);

                return xmlDocument;
            }

            return null;
        }

        /// <summary>
        /// Does a get video thumbnails request.
        /// </summary>
        /// <param name="videoId">The video id.</param>
        /// <returns></returns>
        protected static XmlDocument DoGetVideoThumbnailsRequest(string videoId)
        {
            string output = ExecuteGetCommand
                (BuildOAuthApiRequestUrl(GlobalConstants.VimeoAPI.GetVideoThumbnailsUrl + videoId), 
                null, null);

            if (!string.IsNullOrEmpty(output))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(output);

                return xmlDocument;
            }

            return null;
        }

        /// <summary>
        /// Does the activity request.
        /// </summary>
        /// <param name="vimeoApiOutputFormatType">Type of the vimeo API output format.</param>
        /// <param name="vimeoApiActivityRequestType">Type of the vimeo API activity request.</param>
        /// <param name="username">The username.</param>
        /// <returns></returns>
        protected static string DoActivityRequest
            (VimeoApiOutputFormatType vimeoApiOutputFormatType, 
            VimeoApiActivityRequestType vimeoApiActivityRequestType, string username)
        {
            string url = string.Format(GlobalConstants.VimeoAPI.ActivityRequestUrlFormat, 
                username, GetVimeoApiActivityRequestTypeString(vimeoApiActivityRequestType), 
                GetVimeoApiOutputFormatTypeString(vimeoApiOutputFormatType));
            return ExecuteGetCommand(url, null, null);
        }

        /// <summary>
        /// Does the activity request as XML.
        /// </summary>
        /// <param name="vimeoApiActivityRequestType">Type of the vimeo API activity request.</param>
        /// <param name="username">The username.</param>
        /// <returns></returns>
        protected static XmlDocument DoActivityRequestAsXML
            (VimeoApiActivityRequestType vimeoApiActivityRequestType, string username)
        {
            string output = DoActivityRequest
                (VimeoApiOutputFormatType.XML, vimeoApiActivityRequestType, username);
            if (!string.IsNullOrEmpty(output))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(output);

                return xmlDocument;
            }

            return null;
        }

        /// <summary>
        /// Does the album request.
        /// </summary>
        /// <param name="vimeoApiOutputFormatType">Type of the vimeo API output format.</param>
        /// <param name="vimeoApiAlbumRequestType">Type of the vimeo API album request.</param>
        /// <param name="albumID">The album ID.</param>
        /// <returns></returns>
        protected static string DoAlbumRequest
            (VimeoApiOutputFormatType vimeoApiOutputFormatType, 
            VimeoApiAlbumRequestType vimeoApiAlbumRequestType, string albumID)
        {
            string url = string.Format(GlobalConstants.VimeoAPI.AlbumRequestUrlFormat, albumID,
            GetVimeoApiAlbumRequestTypeString(vimeoApiAlbumRequestType), 
            GetVimeoApiOutputFormatTypeString(vimeoApiOutputFormatType));
            return ExecuteGetCommand(url, null, null);
        }

        /// <summary>
        /// Does the album request as XML.
        /// </summary>
        /// <param name="vimeoApiAlbumRequestType">Type of the vimeo API album request.</param>
        /// <param name="albumId">The album id.</param>
        /// <returns></returns>
        protected static XmlDocument DoAlbumRequestAsXML
            (VimeoApiAlbumRequestType vimeoApiAlbumRequestType, string albumId)
        {
            string output = DoAlbumRequest(VimeoApiOutputFormatType.XML, 
                vimeoApiAlbumRequestType, albumId);
            if (!string.IsNullOrEmpty(output))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(output);

                return xmlDocument;
            }

            return null;
        }

        /// <summary>
        /// Does the channel request.
        /// </summary>
        /// <param name="vimeoApiOutputFormatType">Type of the vimeo API output format.</param>
        /// <param name="vimeoApiChannelRequestType">Type of the vimeo API channel request.</param>
        /// <param name="channelName">The channel ID.</param>
        /// <returns></returns>
        protected static string DoChannelRequest
            (VimeoApiOutputFormatType vimeoApiOutputFormatType, 
            VimeoApiChannelRequestType vimeoApiChannelRequestType, string channelName)
        {
            string url = string.Format(GlobalConstants.VimeoAPI.ChannelRequestUrlFormat, channelName,
            GetVimeoApiChannelRequestTypeString(vimeoApiChannelRequestType), 
            GetVimeoApiOutputFormatTypeString(vimeoApiOutputFormatType));
            return ExecuteGetCommand(url, null, null);
        }

        /// <summary>
        /// Does the channel request as XML.
        /// </summary>
        /// <param name="vimeoApiChannelRequestType">Type of the vimeo API channel request.</param>
        /// <param name="channelName">The channel id.</param>
        /// <returns></returns>
        protected static XmlDocument DoChannelRequestAsXML
            (VimeoApiChannelRequestType vimeoApiChannelRequestType, string channelName)
        {
            string output = DoChannelRequest(VimeoApiOutputFormatType.XML, 
                vimeoApiChannelRequestType, channelName);
            if (!string.IsNullOrEmpty(output))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(output);

                return xmlDocument;
            }

            return null;
        }

        /// <summary>
        /// Does the group request.
        /// </summary>
        /// <param name="vimeoApiOutputFormatType">Type of the vimeo API output format.</param>
        /// <param name="vimeoApiGroupRequestType">Type of the vimeo API group request.</param>
        /// <param name="groupName">The group ID.</param>
        /// <returns></returns>
        protected static string DoGroupRequest
            (VimeoApiOutputFormatType vimeoApiOutputFormatType, 
            VimeoApiGroupRequestType vimeoApiGroupRequestType, string groupName)
        {
            string url = string.Format(GlobalConstants.VimeoAPI.GroupRequestUrlFormat, groupName,
            GetVimeoApiGroupRequestTypeString(vimeoApiGroupRequestType), 
            GetVimeoApiOutputFormatTypeString(vimeoApiOutputFormatType));
            return ExecuteGetCommand(url, null, null);
        }

        /// <summary>
        /// Does the group request as XML.
        /// </summary>
        /// <param name="vimeoApiGroupRequestType">Type of the vimeo API group request.</param>
        /// <param name="groupName">The group id.</param>
        /// <returns></returns>
        protected static XmlDocument DoGroupRequestAsXML
            (VimeoApiGroupRequestType vimeoApiGroupRequestType, string groupName)
        {
            string output = DoGroupRequest(VimeoApiOutputFormatType.XML, 
                vimeoApiGroupRequestType, groupName);
            if (!string.IsNullOrEmpty(output))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(output);

                return xmlDocument;
            }

            return null;
        }
        #endregion

        #region Methods to convert vimeo enums to strings
        /// <summary>
        /// Gets the vimeo API activity request type string.
        /// </summary>
        /// <param name="vimeoApiActivityRequestType">Type of the vimeo API activity request.
        /// </param>
        /// <returns></returns>
        protected static string GetVimeoApiActivityRequestTypeString
            (VimeoApiActivityRequestType vimeoApiActivityRequestType)
        {
            return vimeoApiActivityRequestType.ToString().ToLower();
        }

        /// <summary>
        /// Gets the vimeo API album request type string.
        /// </summary>
        /// <param name="vimeoApiAlbumRequestType">Type of the vimeo API album request.
        /// </param>
        /// <returns></returns>
        protected static string GetVimeoApiAlbumRequestTypeString
            (VimeoApiAlbumRequestType vimeoApiAlbumRequestType)
        {
            return vimeoApiAlbumRequestType.ToString().ToLower();
        }

        /// <summary>
        /// Gets the vimeo API channel request type string.
        /// </summary>
        /// <param name="vimeoApiChannelRequestType">Type of the vimeo API channel request.
        /// </param>
        /// <returns></returns>
        protected static string GetVimeoApiChannelRequestTypeString
            (VimeoApiChannelRequestType vimeoApiChannelRequestType)
        {
            return vimeoApiChannelRequestType.ToString().ToLower();
        }

        /// <summary>
        /// Gets the vimeo API group request type string.
        /// </summary>
        /// <param name="vimeoApiGroupRequestType">Type of the vimeo API group request.
        /// </param>
        /// <returns></returns>
        protected static string GetVimeoApiGroupRequestTypeString
            (VimeoApiGroupRequestType vimeoApiGroupRequestType)
        {
            return vimeoApiGroupRequestType.ToString().ToLower();
        }

        /// <summary>
        /// Gets the vimeo API user request type string.
        /// </summary>
        /// <param name="vimeoApiUserRequestType">Type of the vimeo API user request.
        /// </param>
        /// <returns></returns>
        protected static string GetVimeoApiUserRequestTypeString
            (VimeoApiUserRequestType vimeoApiUserRequestType)
        {
            return vimeoApiUserRequestType.ToString().ToLower();
        }

        /// <summary>
        /// Gets the vimeo API output format type string.
        /// </summary>
        /// <param name="vimeoApiOutputFormatType">Type of the vimeo API output format.
        /// </param>
        /// <returns></returns>
        protected static string GetVimeoApiOutputFormatTypeString
            (VimeoApiOutputFormatType vimeoApiOutputFormatType)
        {
            return vimeoApiOutputFormatType.ToString().ToLower();
        }
        #endregion

        /// <summary>
        /// Gets the video title from vimeo.
        /// </summary>
        /// <param name="videoId">The video id.</param>
        /// <returns></returns>
        public static string GetVideoTitleFromVimeo(string videoId)
        {
            var video = GetVideoUsingVideoId(videoId);

            return video == null ? string.Empty : video.title;
        }

        /// <summary>
        /// Gets the embedded player HTML.
        /// </summary>
        /// <param name="videoId">The video id.</param>
        /// <returns></returns>
        public static string GetEmbeddedPlayerHTML(string videoId)
        {
            var doc = DoOembedRequestAsXML(videoId);

            var serializer = new XmlSerializer(typeof(OEmbed));

            var stringReader = new StringReader(doc.OuterXml);
            var xmlReader = new XmlTextReader(stringReader);

            var oembed = (OEmbed)serializer.Deserialize(xmlReader);

            return oembed.html;
        }

        /// <summary>
        /// Gets the vimeo video id from URL.
        /// </summary>
        /// <param name="videoURL">The video URL.</param>
        /// <returns>The video Id</returns>
        public static string GetVimeoVideoIdFromURL(string videoURL)
        {
            if (videoURL.Contains("/"))
            {
                var splitter = videoURL.Split(new[] {'/'});

                return splitter[splitter.Length - 1];
            }
            
            int v;
            return int.TryParse(videoURL, out v) ? videoURL : string.Empty;
        }

        /// <summary>
        /// Gets the video using video id.
        /// </summary>
        /// <param name="videoId">The video id.</param>
        /// <returns>VimeoVideo object</returns>
        public static VimeoVideo GetVideoUsingVideoId(string videoId)
        {
            var xmldoc = RequestInXML.Video.GetVideo(videoId);

            var serializer = new XmlSerializer(typeof(VimeoVideoWrapper));

            var stringReader = new StringReader(xmldoc.OuterXml);
            var xmlReader = new XmlTextReader(stringReader);

            var video = (VimeoVideoWrapper)serializer.Deserialize(xmlReader);

            if (video.Videos == null || video.Videos.Length == 0)
                return null;

            return video.Videos[0];
        }

        /// <summary>
        /// Builds the vimeo search response.
        /// </summary>
        /// <param name="xmldoc">The xmldoc.</param>
        /// <returns></returns>
        public static VimeoSearchResponse BuildVimeoSearchResponse(XmlDocument xmldoc)
        {
            try
            {
                var serializer = new XmlSerializer(typeof(VimeoSearchResponse));

                var stringReader = new StringReader(xmldoc.OuterXml);
                var xmlReader = new XmlTextReader(stringReader);

                return (VimeoSearchResponse) serializer.Deserialize(xmlReader);
            }
            catch {}

            return null;
        }

        /// <summary>
        /// Builds the vimeo video thumbnails response.
        /// </summary>
        /// <param name="xmldoc">The xmldoc.</param>
        /// <returns></returns>
        public static VimeoVideoThumbnailsResponse BuildVimeoVideoThumbnailsResponse
            (XmlDocument xmldoc)
        {
            try
            {
                var serializer = new XmlSerializer(typeof(VimeoVideoThumbnailsResponse));

                var stringReader = new StringReader(xmldoc.OuterXml);
                var xmlReader = new XmlTextReader(stringReader);

                return (VimeoVideoThumbnailsResponse)serializer.Deserialize(xmlReader);
            }
            catch { }

            return null;
        }

        /// <summary>
        /// Builds the vimeo error response.
        /// </summary>
        /// <param name="xmldoc">The xmldoc.</param>
        /// <returns></returns>
        public static VimeoErrorResponse BuildVimeoErrorResponse(XmlDocument xmldoc)
        {
            try
            {
                var serializer = new XmlSerializer(typeof(VimeoErrorResponse));

                var stringReader = new StringReader(xmldoc.OuterXml);
                var xmlReader = new XmlTextReader(stringReader);

                return (VimeoErrorResponse)serializer.Deserialize(xmlReader);
            }
            catch { }

            return null;
        }

        /// <summary>
        /// Searches the specified query.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <returns></returns>
        public static XmlDocument Search(string query)
        {
            try
            {
                return DoSearchRequest(query);
            }
            catch { }

            return null;
        }

        /// <summary>
        /// Gets the video thumbnails.
        /// </summary>
        /// <param name="videoId">The video id.</param>
        /// <returns></returns>
        public static XmlDocument GetVideoThumbnails(string videoId)
        {
            try
            {
                return DoGetVideoThumbnailsRequest(videoId);
            }
            catch { }

            return null;
        }

        /// <summary>
        /// Checks the query worked ok.
        /// </summary>
        /// <param name="xmldoc">The xmldoc.</param>
        /// <returns></returns>
        public static bool QueryIsOk(XmlDocument xmldoc)
        {
            try
            {
                if (xmldoc.DocumentElement != null)
                    return xmldoc.DocumentElement.GetAttribute("stat").Equals("ok");
            }
            catch { }

            return false;
        }
    }
}

 

This is our wrapper of the Vimeo API. As I mentioned at the start there are a lot of methods in here that are not needed for this project, but if you are planning to get more involved with the Vimeo API I’m sure you’ll be grateful that they’re there!

Next we’ll add a couple of pages to our web application.

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" 
Inherits="Vimeo.Default" %>
<%@ Import Namespace="Common" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Vimeo test</title>
</head>
<body>
    <form id="form1" runat="server">
        <label>Search Vimeo:</label> 
        <asp:TextBox ID="VimeoSearchQuery" runat="server"></asp:TextBox> 
        <asp:LinkButton ID="VimeoSearchQueryBtn" runat="server" 
            OnClick="VimeoSearchQueryBtn_Click" Text="Search"></asp:LinkButton>

        <asp:Label ID="ErrorMessage" runat="server" Visible="false"></asp:Label>
                
        <asp:PlaceHolder ID="phSearchResults" runat="server"></asp:PlaceHolder>
        
        <div id="divSearchResults">
            <asp:Repeater ID="SearchResultsRepeater" runat="server">
                <ItemTemplate>
                <div>
                    <a href="<%= GlobalConstants.Links.ViewVideo %>
                        <%#DataBinder.Eval(Container.DataItem, "VideoId")%>">
                            <%#DataBinder.Eval(Container.DataItem, "Thumbnail")%>
                    </a>
                    <br />
                    <a href="<%= GlobalConstants.Links.ViewVideo %>
                        <%#DataBinder.Eval(Container.DataItem, "VideoId")%>">
                            <%#DataBinder.Eval(Container.DataItem, "Title")%>
                    </a>
                </div>
                </ItemTemplate>
            </asp:Repeater>
        </div>
    </form>
</body>
</html>

Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Web.UI;
using BusinessObject;
using BusinessObject.Enums;
using Common;

namespace Vimeo
{
    public partial class Default : Page
    {
        /// <summary>
        /// Handles the Click event of the VimeoSearchQueryBtn control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> 
        /// instance containing the event data.</param>
        protected void VimeoSearchQueryBtn_Click(object sender, EventArgs e)
        {
            var response = VimeoAPI.Search(VimeoSearchQuery.Text);

            if (VimeoAPI.QueryIsOk(response))
            {
                var vimeoSearchResponse = VimeoAPI.BuildVimeoSearchResponse(response);

                var videoList = new List<VideoExtracted>();

                if (vimeoSearchResponse.videos.total != "0")
                {
                    foreach (var video in vimeoSearchResponse.videos.video)
                    {
                        var thumbnail = GetMediumVimeoThumbnail(video.id);

                        if (!string.IsNullOrEmpty(thumbnail))
                            videoList.Add(new VideoExtracted
                            {
                                Thumbnail = "<img src=\"" + thumbnail + "\" />",
                                Title = video.title,
                                VideoId = video.id
                            });
                    }
                }

                BindSearchRepeaterAndAddToCache(videoList);
            }
            else
            {
                var vimeoErrorResponse = VimeoAPI.BuildVimeoErrorResponse(response);

                DisplayErrorMessage(
                    (VimeoApiErrorCode) Convert.ToInt32(vimeoErrorResponse.error.code) ==
                        VimeoApiErrorCode.ServiceCurrentlyUnavailable
                            ? GlobalConstants.ErrorMessages.SearchServiceUnavailable
                            : GlobalConstants.ErrorMessages.SearchError);
            }
        }

        /// <summary>
        /// Binds the search repeater add add to cache.
        /// </summary>
        /// <param name="videoList">The video list.</param>
        private void BindSearchRepeaterAndAddToCache(IEnumerable<VideoExtracted> videoList)
        {
            SearchResultsRepeater.DataSource = videoList;
            SearchResultsRepeater.DataBind();

            if (SearchResultsRepeater.Items.Count > 0)
                phSearchResults.Visible = true;
            else
            {
                DisplayErrorMessage(GlobalConstants.ErrorMessages.NoSearchResults);
                phSearchResults.Visible = false;
            }
        }

        /// <summary>
        /// Gets the medium vimeo thumbnail.
        /// </summary>
        /// <param name="videoId">The video id.</param>
        /// <returns></returns>
        protected string GetMediumVimeoThumbnail(string videoId)
        {
            var response = VimeoAPI.GetVideoThumbnails(videoId);

            if (VimeoAPI.QueryIsOk(response))
            {
                var vimeoVideoThumbnailsResponse = 
                    VimeoAPI.BuildVimeoVideoThumbnailsResponse(response);

                return vimeoVideoThumbnailsResponse.thumbnails.thumbnail[1].thumbnail;
            }

            return null;
        }

        /// <summary>
        /// Displays the error message.
        /// </summary>
        /// <param name="errorMessage">The error message.</param>
        private void DisplayErrorMessage(string errorMessage)
        {
            ErrorMessage.Visible = true;
            ErrorMessage.Text = errorMessage;
            return;
        }
    }
}

So what’s going on here? Well when we click the search button on the front page we call our VimeoAPI.Search() method with the search text. The VimeoAPI.Search method then calls several methods within our VimeoAPI wrapper. First it creates an OAuth request url with our consumer key, consumer secret and search query in BuildOAuthApiRequestUrl() and DoSearchRequest(), then it calls the Vimeo web service in ExecuteGetCommand() method. ExecuteGetCommand() return an XML response which is then loaded into an XmlDocument() which we return to the Default.aspx.cs VimeoSearchQueryBtn_Click() method.

Once the code behind gets the XmlDocument we check the response code is valid by calling VimeoAPI.QueryIsOk(). If the response is not OK we output an error message, otherwise we serialize the XmlDocument into our VimeoVideo class using VimeoAPI.BuildVimeoSearchResponse().

This is the basics behind any call you will make to the VimeoAPI and it is simply a case of ensuring you have the correct request URL with valid consumer key and consumer secret, and a serializable class (if you want to take the serialize route and aren’t going to manually wade through the XML!) to put the XML response from your call in to.

For the purposes of this example I have created a List<VideoExtracted>() item to which I add each video returned by the search call to the API along with a thumbnail for that video which I have to get by calling the API for each video. It would be nice if the thumbnails were returned with the search list of videos, but at the time of writing that isn’t the case.

Bind this list of VideoExtracted items to our repeater and this page is done.

Lastly, the video viewer page.

ViewVideo.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ViewVideo.aspx.cs" 
    Inherits="Vimeo.ViewVideo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Vimeo Player Test</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <h2><asp:Literal ID="VideoTitle" runat="server"></asp:Literal></h2><br />
        
            <p><asp:Literal ID="VideoDescription" runat="server"></asp:Literal></p>

            <div id="thevideo" runat="server"></div>
        </div>
    </form>
</body>
</html>

ViewVideo.aspx.cs

using System;
using System.Web.UI;
using Common;

namespace Vimeo
{
    public partial class ViewVideo : Page
    {
        /// <summary>
        /// Handles the Load event of the Page control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> 
        /// instance containing the event data.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            var vidId = Request.QueryString[GlobalConstants.Querystring.Video];

            thevideo.InnerHtml = VimeoAPI.GetEmbeddedPlayerHTML(vidId);

            var video = VimeoAPI.GetVideoUsingVideoId(vidId);

            VideoTitle.Text = video.title;
            VideoDescription.Text = video.description;
        }

        /// <summary>
        /// Replaces the line break with BR.
        /// </summary>
        /// <param name="s">The s.</param>
        /// <returns></returns>
        public static string ReplaceLineBreakWithBR(string s)
        {
            return s.Replace("\r\n", "<br />").Replace("\n", "<br />");
        }
    }
}

 

Very simple, a video id is passed in the querystring, retrieved in the Page_Load() method of the page and the video details are retrieved by calling the VimeoAPI.GetVideoUsingVideoId() method. the HTML for the video to display on the page is built by performing an OEmbed request to the Vimeo API using the VimeoAPI.DoOembedRequestAsXML() method. This again uses our VimeoAPI.ExecuteGetCommand() method and works like the other requests we have seen.

Conclusion

I hope that was relatively painless and makes sense. As always the best way to fully understand what’s going on in the code is to download the source and have a play around with it. Until next time…  :o)

Tags:

Share |

Comments

8/13/2010 1:23:46 PM #

Amol Choudhari

Hi Rob I had downloaded your code but I am gettint error that it needs to be converted as it is buit in higher version.Is their any option for this to use it in VS 2005 with .net framework 2.0

Amol Choudhari India |

8/13/2010 1:30:44 PM #

Rob

Sorry yes it's built in VS2010. I'll do a VS2005 version and post it up over the weekend for you  :o)

Rob United Kingdom |

8/13/2010 2:56:37 PM #

Rob

Now done - check for the VS2005 link at the top of the post. Have fun  :o)

Rob United Kingdom |

Contact   |   Archive   |   Log in

Powered by BlogEngine.NET 1.6.1.0