YouTubeService service = new YouTubeService("NETUnittests", this.ytClient, this.ytDevKey);
service.Credentials = new GDataCredentials(this.ytUser, this.ytPwd);
GDataRequestFactory factory = service.RequestFactory as GDataRequestFactory;
factory.Timeout = 1000000;
YouTubeEntry entry = new YouTubeEntry();
entry.MediaSource = new MediaFileSource(this.resourcePath + "test_movie.mov", "video/quicktime");
entry.Media = new YouTube.MediaGroup();
entry.Media.Description = new MediaDescription("This is a test with and & in it");
entry.Media.Title = new MediaTitle("Sample upload");
entry.Media.Keywords = new MediaKeywords("math");
// entry.Media.Categories
MediaCategory category = new MediaCategory("Nonprofit");
category.Attributes["scheme"] = YouTubeService.DefaultCategory;
entry.Media.Categories.Add(category);
YouTubeEntry newEntry = service.Upload(this.ytUser, entry);
To insert a new video, you need to create a service object, set the timeout on the service to a reasonable amount, create a new YouTubeEntry object, create a MediaSource on that object, set the properties on that media source, add a category, and at the end upload the entry using the service upload method. Not too complicated, in general.
If you wanted to iterate over a feed, this is the code you were writing:
YouTubeQuery query = new YouTubeQuery(YouTubeQuery.TopRatedVideo);
YouTubeService service = new YouTubeService("NETUnittests", this.ytClient, this.ytDevKey);
service.Credentials = new GDataCredentials(this.ytUser, this.ytPwd);
query.Formats.Add(YouTubeQuery.VideoFormat.RTSP);
query.Time = YouTubeQuery.UploadTime.ThisWeek;
YouTubeFeed feed = service.Query(query);
foreach (YouTubeEntry e in feed.Entries )
{
Console.WriteLine(e.Media.Title.Value);
}
Again, the code is pretty straightforward. Create a service object, create a query, have a loop to go over the data. But, as you are aware, the loop above will only return 25 entries, or whatever the service default is. So while you wanted all TopRatedVideos, you in fact, only got a part of it. To get more, you need to page by checking the feeds nextChunk property and executing another query.
This was well as long as you were trying to retrieve required elements. An entry object is required to have a Summary, but the code above e.Media.Title.Value can actually crash on you, as e.Media might return NULL - while YouTube entries are unlikely to have no Media subelement, the implementation code would return a null element if none is found.
And that is one of the more fundamental problems with the protocol based object model. Due to the nature of the beast, you will end up with a lot of code that looks like this:
if (youTubeEntry != null &&
youTubeEntry.Media != null &&
youTubeEntry.Media.Description != null)
{
Console.WriteLine(youTubeEntry.Media.Description.Value);
In the new model, we are trying to hide a lot of the checks above, and make iteration over feeds easier. Let's look at how looping over a feed looks like, and what objects are involved.
YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytClient, this.ytDevKey, this.ytUser, this.ytPwd);
YouTubeRequest f = new YouTubeRequest(settings);
Feed<Video> feed = f.GetStandardFeed(YouTubeQuery.MostPopular);
foreach (Video v in feed.Entries)
{
Feed<Comment> list = f.GetComments(v);
foreach (Comment c in list.Entries)
{
Console.WriteLine(c.Title);
}
}
A YouTubeRequestSettings object holds the information needed to connect to the YouTubeServer. Username, password, developer key etc. There are several different constructors (for anonymous access or AuthSub access). You pass this object to a YouTubeRequest object. The request object is your representation of the server in this code. You want data, you want to send data, that's the object that does it. No more entry.Update() or feed.Insert().
From the YouTubeRequest, you get a generic type back, a feed of Videos in this case. You loop over that feed, and want to retrieve a comment feed for the video. So you return to the YouTubeRequest and ask for a comment feed for the current video. This time you get a feed of comments and you can iterate over this again.
As mentioned above, the server will normally only return a page full of data, and that is true here as well. So we loop over the 25 top videos, and then the first 25 comments of that. To change this behaviour, we need to add one line of code:
YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytClient, this.ytDevKey, this.ytUser, this.ytPwd);
settings.AutoPaging = true;
YouTubeRequest f = new YouTubeRequest(settings);
Feed<Video> feed = f.GetStandardFeed(YouTubeQuery.MostPopular);
foreach (Video v in feed.Entries)
{
Feed<Comment> list = f.GetComments(v);
foreach (Comment c in list.Entries)
{
Console.WriteLine(c.Title);
}
}
That one line, settings.Autopaging = true, results in the iterator that is used when we loop over the entries collection to automatically request new data from the server when we reach the end of the current set. As the most popular feed is limited to a fixed set of videos, this will iterate over 50 videos, by requesting 2 set of results from the server, and get all comments for those videos.
If you wanted to say: yes, get me all data, up to a certain maximum, you add another line of code:
YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytClient, this.ytDevKey, this.ytUser, this.ytPwd);
settings.AutoPaging = true;
settings.Maximum = 15;
YouTubeRequest f = new YouTubeRequest(settings);
Feed<Video> feed = f.GetStandardFeed(YouTubeQuery.MostPopular);
foreach (Video v in feed.Entries)
{
Feed<Comment> list = f.GetComments(v);
foreach (Comment c in list.Entries)
{
Console.WriteLine(c.Title);
}
}
The Maximum property of the YouTubeRequestSettings allows you to specify that the iterators will stop at this maximum, no matter how much more data might be available.
As you can see in the code below, the main difference is that the creation of the in-between objects (like Media or MediaDesription in the old code), is no longer required. The Timeout as well is easily accessible directly on the YouTubeRequestSettings object.
YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytClient, this.ytDevKey, this.ytUser, this.ytPwd);
settings.Timeout = = 1000000;
YouTubeRequest f = new YouTubeRequest(settings);
Video v = Video.CreateInstance();
v.Title = "Sample upload";
v.Description = "This is a test with and & in it";
MediaCategory category = new MediaCategory("Nonprofit");
category.Attributes["scheme"] = YouTubeService.DefaultCategory;
v.Tags.Add(category);
v.Keywords = "math";
v.YouTubeEntry.MediaSource = new MediaFileSource(this.resourcePath + "test_movie.mov", "video/quicktime");
Video newVideo = f.Upload(this.ytUser, v);
But overall for creating new video, while the code looks nicer and is slightly less verbose, this is not introducing a significant code saving as it is for the read case before.