Return to Snippet

Revision: 16739
at August 14, 2009 02:07 by CVertex


Initial Code
public interface IUrlShorteningService
    {
        string Shorten(string longUrl);
    }

    public class UrlShorteningServiceException : Exception {
        public UrlShorteningServiceException(string message)
            : base(message) {
            }

        public UrlShorteningServiceException(string message, Exception innerException)
            : base(message, innerException) {
            }
    }

    public class BitlyServiceException : UrlShorteningServiceException {

        public BitlyServiceException(int errorCode, string message)
            : base(message) {
            ErrorCode = errorCode;
            }


        public BitlyServiceException(int errorCode, string message, Exception innerException)
            : base(message, innerException) {
            ErrorCode = errorCode;
            }

        public int ErrorCode { get; private set; }
    }

    public class BitlyShorteningService : IUrlShorteningService {
        private const string _version = "2.0.1";
        private readonly string _apiKey;
        private readonly string _login;
        private bool _useCache = false;
        private Func<string, string> _shortener;
        private readonly JavaScriptSerializer _javaScriptSerializer;
        
        //http://api.bit.ly/shorten?version=2.0.1&longUrl=http://cnn.com&login=bitlyapidemo&apiKey=R_0da49e0a9118ff35f52f629d2d71bf07
        const string _baseShortenUrl = "http://api.bit.ly/shorten";

        #region ctors

        public BitlyShorteningService(string login, string apiKey, bool useCache) {
            _login = login;
            _apiKey = apiKey;
            _javaScriptSerializer = new JavaScriptSerializer();
            UseCache = useCache;
            EnsureShortenerCore();
        }

        public BitlyShorteningService(string login, string apiKey):this(login,apiKey,false) { }

        #endregion
        
        #region Caching

        public bool UseCache {
            get {
                return _useCache;
            }
            set {
                if (value == _useCache) // no change
                {
                    return;
                }

                // use cache has changed, so change the shortener
                _useCache = value;
                SetShortenerCore();
            }
        }
        
        private void EnsureShortenerCore()
        {
            if (_shortener==null)
            {
                SetShortenerCore();
            }
        }

        private void SetShortenerCore()
        {
            if (_useCache)
            {
                _shortener = new Func<string, string>(ShortenCore).Memoize();    
            } else
            {
                _shortener = ShortenCore;
            }
            

        }

        
        #endregion
        
        #region Bit.ly objects

        class Response<T> {
            public int errorCode;
            public string errorMessage;
            public Dictionary<string, T> results;
        }

        class Result {
            public string hash;
            public string userHash;
            public string shortKeywordUrl;
            public string shortUrl;


        }

        #endregion

        #region Shortening

        public string Shorten(string longUrl)
        {
            if (_shortener == null)
                return "";

            return _shortener(longUrl);
        }

        protected virtual string ShortenCore(string longUrl) {
            if (longUrl == null) throw new ArgumentNullException("longUrl");

            try {

                var uri = new UrlBuilder(_baseShortenUrl);
                uri.QueryString["login"] = _login;
                uri.QueryString["apiKey"] = _apiKey;
                uri.QueryString["version"] = _version;
                uri.QueryString["longUrl"] = longUrl;

                using (var web = new WebClient()) {
                    var resultString = web.DownloadString(uri.ToString());
                    var result = _javaScriptSerializer.Deserialize<Response<Result>>(resultString);
                    if (result.errorCode != 0) {
                        throw new BitlyServiceException(result.errorCode, result.errorMessage);
                    }
                    return result.results[longUrl].shortUrl;
                }



            } catch (Exception ex) {
                throw new UrlShorteningServiceException(String.Format("Error shortening long URL {0} with bit.ly",longUrl), ex);
            }


        }

        #endregion
    }

Initial URL


Initial Description


Initial Title
URL Shortening Service Contract w/ Bitly Implementation

Initial Tags
url, http, c

Initial Language
C#