ODATA

Using the HttpClient and the OData service to download Mix videos

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. 

ODATA

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<Atom10FeedFormatter>().Feed;

    var files = from it in filesDocument.Items
                let uri = it.GetMediaResourceUri()
                where it.Content.Type == "video/x-ms-wmv" && !uri.ToString().Contains("wmv-hq")
                select uri;

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

    }
}

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)

Related Blog