I needed the ability to shorten a URL for a WP7 app the other day so I could share a URL via the ShareLinkTask, more info about this task can be found on MSDN. What follows is a solution to shortening a URL programmtically using tinyurl.com.
The implementation for in the WP7Contrib is as follows, it uses the Rx (reactive extensions) async method to make the request over HTTP and process the response. If processing the response fails then the original URL is returned - if it fails to call the TinyUrl server it will return the original value as the shortened URL.
This has now been added to the WP7Contrib. There is an example of how to use this in the Spikes directory called 'UrlShortenerDemo'.
Obviously shortening a URL from a phone requires a connection, so this might not be applicable to a lot of apps. The problem is not the actual connection but the quality of said connection. When tethered or on WIFI the time required to shorten a URL is insignificant, but when on 3G the time is very noticable.
The solution I came up with allowed me to be abstracted away from the under lying HTTP request, infact it allowed me to write the code in 3 lines of code!
private void HandleShortenButtonClick(object sender, RoutedEventArgs e) { this.tinyUrlShortener.Shorten(this.url.Text) .ObserveOnDispatcher() .Subscribe(u => this.shortenedUrl.Text = u); }
The implementation for in the WP7Contrib is as follows, it uses the Rx (reactive extensions) async method to make the request over HTTP and process the response. If processing the response fails then the original URL is returned - if it fails to call the TinyUrl server it will return the original value as the shortened URL.
public IObservable<string> Shorten(string url) { if (string.IsNullOrEmpty(url)) { throw new ArgumentException("Can reduce a null or empty url!", "url"); } try { this.log.Write(string.Format("TinyUrlShortener: Url - '{0}'.", url)); return Observable.Defer<string>(() => Observable.Create<string>(obs => { var disposable = new BooleanDisposable(); try { var requestUrl = string.Format("http://tinyurl.com/api-create.php?url={0}", this.propertyEncoder.Encode(url)); this.log.Write(string.Format("TinyUrlShortener: Tiny url - '{0}'.", requestUrl)); var request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(requestUrl)); request.Method = "GET"; request.AllowAutoRedirect = true; request.CookieContainer = new CookieContainer(); Observable.FromAsyncPattern(request.BeginGetResponse, ar => { try { var shortenedUrl = url; if (disposable.IsDisposed) { return; } using (var response = (HttpWebResponse)request.EndGetResponse(ar)) { if (response.StatusCode == HttpStatusCode.OK) { using (var stream = new StreamReader(response.GetResponseStream())) { shortenedUrl = stream.ReadLine(); } } } this.log.Write(string.Format("TinyUrlShortener: Shortened url - '{0}'.", shortenedUrl)); obs.OnNext(shortenedUrl); obs.OnCompleted(); } catch (Exception exn) { var message = string.Format(FailedRequest, exn.Message); obs.OnError(new ServiceException(message, exn)); } })(); } catch(Exception exn) { var message = string.Format(FailedRequest, exn.Message); obs.OnError(new ServiceException(message, exn)); } return disposable; })); } catch (Exception exn) { var message = string.Format("TinyUrlShortener: Failed to shorten url, message - '{0}'.", exn.Message); this.log.Write(message); throw new ServiceException(message, exn); } }
This has now been added to the WP7Contrib. There is an example of how to use this in the Spikes directory called 'UrlShortenerDemo'.
Comments
Post a Comment