Using the HttpClient and the OData service to download Mix videos

Published on March 20, 2010

Here is some code I wrote to give me some experience playing with an OData service, learning more Linq, using my favourite HTTP client library and getting to download mix videos. 

It will download only the videos related to the tag name that you specify and currently it is set to download the low quality wmv files.  Feel free to pick whatever content type you like!

You will need the http client library that is buried in here, and you need to set the tagName to whatever interests you, other than that, it should just work.  Please note, there is only one hardcoded url in this client :-)

If you have questions, you can usually find me on twitter @@darrelmiller

 

var httpClient = new HttpClient("http://api.visitmix.com/OData.svc");

string tagName = "REST";

var serviceDocument = httpClient.Get().Content.ReadAsDataContract<AtomPub10ServiceDocumentFormatter>().Document; ;

// Get Url for Tags collection var tagsUrl = (from co in serviceDocument.Workspaces[0].Collections where co.Title.Text == "Tags" select new Uri(serviceDocument.BaseUri, co.Link)).FirstOrDefault();

var tagsDocument = httpClient.Get(tagsUrl).Content.ReadAsDataContract<Atom10FeedFormatter>().Feed;

// Find Sessions Link for tag var sessionsUri = (from tg in tagsDocument.Items from lk in tg.Links where tg.Title.Text == tagName && lk.RelationshipType == "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Sessions" select new Uri(tagsDocument.BaseUri, lk.Uri)).First();

// Follow the link to get the list of sessions var sessionsForTagFeed = httpClient.Get(sessionsUri).Content.ReadAsDataContract<Atom10FeedFormatter>().Feed; ;

// Get the files links for each session var sessionFileLinks = (from st in sessionsForTagFeed.Items from lk in st.Links where lk.RelationshipType == "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Files" select new Uri(sessionsForTagFeed.BaseUri,lk.Uri) );

// Loop through each list of files and download foreach (Uri sessionFilesLink in sessionFileLinks) {

var filesDocument = httpClient.Get(sessionFilesLink).Content.ReadAsDataContract&lt;Atom10FeedFormatter&gt;().Feed;

var files = from it <span class="kwrd">in</span> filesDocument.Items
            let uri = it.GetMediaResourceUri()
            <span class="kwrd">where</span> it.Content.Type == <span class="str">&quot;video/x-ms-wmv&quot;</span> &amp;&amp; !uri.ToString().Contains(<span class="str">&quot;wmv-hq&quot;</span>)
            select uri;

<span class="kwrd">foreach</span> (Uri uri <span class="kwrd">in</span> files) {
    <span class="kwrd">try</span> {
        var response = httpClient.Get(uri);
        var filename = uri.Segments.Last();
        <span class="kwrd">using</span> (var file = <span class="kwrd">new</span> FileStream(filename, FileMode.CreateNew)) {
            response.Content.WriteTo(file);
            response.EnsureStatusIsSuccessful();
        }
    }
    <span class="kwrd">catch</span> (WebException ex) {
        Console.WriteLine(<span class="str">&quot;Failed to download &quot;</span> + uri.ToString() + <span class="str">&quot; : &quot;</span> + ex.Message);
        <span class="rem">// Continue onto next</span>
    }

}

}

 

Just paste this code into a Console app and add references to the following DLL’s

  • System.ServiceModel.Web (.Net 3.5)
  • System.Runtime.Serialization
  • Microsoft.Http  ( found in Program Files (x86)Microsoft WCF RESTWCF REST Starter Kit Preview 2Assemblies)
  • Microsoft.Http.Extensions  ( as above)