How to use Google Data API in ASP.NET MVC. Part 2 – YouTube
Previously on this series, I had talked about How to use Google Data API in ASP.NET MVC to interact with Google Analytics. In this second part I'm going to show you how to store and retrieve videos on/from YouTube using Google Data API and YouTube API.
YouTube is the largest and most popular video sharing website and since Google has acquired it and integrated its API into GData it's been an ultimate choice for developers to choose it as a safe and powerful backend for their videos.
I should mention that there are two types of YouTube APIs for developers:
- The Data API which lets you incorporate YouTube functionality into your own application or website. You can perform searches, upload videos, create playlists, and more.
- The Player APIs which give you control over YouTube video playback on your website. Configure basic settings, drive the player interface, or even build your own player controls.
One may add the third Custom Player to the list above but indeed it's not an API.
In our tutorial we will go through the first item: Data API; the second is left for JS and AS developers and maybe Pedram would write about it!
Well, let's go!
I'll divide my blog post main content into two seperate topics: Storing Videos and Retrieving Video.
Storing Videos on YouTube
First of all your have to prepare required tools to interact with YouTube Data API. Here's what you would do:
- Sign up for a developer key. You will also need your Google account username and password.
- Download YouTube SDK.
After installing YouTube SDK, reference the following assemblies in your project:
using Google.GData.Client; using Google.GData.Extensions; using Google.GData.YouTube; using Google.GData.Extensions.MediaRss; using Google.YouTube;
Whenever you want to send/receive data to/from YouTube you should authenticate yourself (your application) against it. The following helper method first checks if there is already an authenticated request object in Session and use it for the current request as well, otherwise it will create a new YouTubeRequest using the YouTubeRequestSettings which we provide:
public static YouTubeRequest GetRequest()
{
var request = HttpContext.Current.Session["YTRequest"] as YouTubeRequest;
if (request == null)
{
var settings = new YouTubeRequestSettings("SampleWebApp", "NA",
ConfigurationManager.AppSettings["YouTubeAPIDeveloperKey"],
ConfigurationManager.AppSettings["YouTubeUsername"],
ConfigurationManager.AppSettings["YouTubePassword"]);
request = new YouTubeRequest(settings);
HttpContext.Current.Session["YTRequest"] = request;
}
return request;
}
Now we are ready to create a view to let the end user browse his video file and upload it to YouTube:
<%
var youTubeRequest = GetRequest();
var newVideo = new Video { "VideoTitle", Description = "VideoDescription" };
newVideo.Media.Categories.Add(new MediaCategory("All")); // You can assign any category here.
newVideo.Keywords = "samplekeyword";
newVideo.YouTubeEntry.Private = false;
var token = youTubeRequest.CreateFormUploadToken(newVideo);
var postUrl = token.Url;
var tokenValue = token.Token;
%>
<% if ((bool)ViewData["UploadError"])
{%>
<%= "Error uploading the video!" %>
<%} %>
<form action="<%= postUrl %>?nexturl=http://localhost/upload/success" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="hidden" name="token" value="<%= tokenValue %>" />
<input type="submit" value="Upload!" />
</form>
The code above consisted of two parts; first we create a YouTubeRequest object (using the helper method which we built before) and then we prepare the required YouTube Video object which contains our video meta data information. One thing I've experienced using this Video object is that you MUST specify a MediaCategory and also some Keywords; otherwise you will receive a bad request error. After assigning the required properties to our Video object, we need to request a token value. A token is used by YouTube API to recognize your request and prevent duplicate requests. This token provide us with a Url property that would be used to post uploaded file to. We've also implemented a simple error handling section to show a friendly error message if uploading process failed. The second part of the code shows an HTML <form> tag that lets you upload a video file. Action value is our "postUrl" variable which we created before plus a nextUrl query string value - the page which you want to return back to when the upload process is completed.
When you uploaded a video successfully you would be automatically redirected to the page which you specified in nextUrl query string value. YouTube API sends back some information along with this nextURL. You will receive Video ID (something like "mLw7ySQFuV4") and an integer Status Code. If Status Code doesn't equal 200 it means something went wrong and you should return a friendly error message and ask your user try again; otherwise, upload process has been successful. The action method behind "/success" URL is shown below:
public ActionResult Success(int status, string id)
{
if (status != 200) // Upload was not successful. Checking the status code.
{
ViewData["UploadError"] = true;
return RedirectToAction("Upload");
}
// Now you should store uploaded video information using your Data Access layer / Repository.
// This is the place in which you should set Video ID returned back to this action from YouTube API.
// This ID (in form of XXXXXXXXXXX) will be used to retrieve a video to edit or play.
return RedirectToAction("Manage");
}
Learn more about different status codes here.
I recommend you split your upload operation into two steps: first let the end user enter video meta data like title, description, tags, etc. and store them in your database then ask him to upload and attach the video file to this record. This way it's easy to track video properties state when an error accures and you have to show back the upload view again.
Congratulations! You uploaded and stored your first video onYouTube from inside your application using YouTube API.
Retrieving a Video from YouTube
Now you have a real video under the account that you have used to authenticate against YouTube. Two other common scenarios you may want to implement are editing an existing video (either changing meta data information or replacing the video file with a new one) and the second is playing that video.
In both scenarios we should retreive the video object first. Logic behind this, is similar to what we've implemented to create a new video entry with a some minor differences:
var youTubeRequest = YouTubeHelper.GetRequest();
var videoEntryUrl = new Uri(string.Format("http://gdata.youtube.com/feeds/api/users/{0}/uploads/{1}",
ConfigurationManager.AppSettings["YouTubeUserId"], youTubeId));
var youTubeVideo = youTubeRequest.Retrieve<Google.YouTube.Video>(videoEntryUrl);
Now you have the existing Video object ready and can change its meta data information or create a new token value to upload a new video file.
Playing the video (using YouTube pre-built player) is very easy as well. Just pass Video ID to Play action method and retrieve it from YouTube as shown in the code above; then pass it to the respected view:
public ActionResult Play(string youTubeId)
{
var youTubeRequest = YouTubeHelper.GetRequest();
var videoEntryUrl = new Uri(string.Format("http://gdata.youtube.com/feeds/api/users/{0}/uploads/{1}",
ConfigurationManager.AppSettings["YouTubeUserId"], youTubeId));
var youTubeVideo = youTubeRequest.Retrieve<Google.YouTube.Video>(videoEntryUrl);
return View(youTubeVideo);
}
Final step is using the model in a view page. I have used popular SWFObject to ebmed YouTube player in my view:
<script type="text/javascript">
var params = { allowScriptAccess: "always" };
var atts = { id: "myytplayer" };
swfobject.embedSWF("http://www.youtube.com/v/<%= Model.VideoId %>?enablejsapi=1&playerapiid=ytplayer",
"ytapiplayer", "625", "556", "8", null, null, params, atts);
</script>
You're done!
Please note that I have tried to simplify all steps and customize everything for an ASP.NET MVC app scenario and in real world scenarios your should provide your end user with more features and customization options.
Create a Twitter API proxy for your own!
As you may know I live in Iran and many websites are blocked here due to governmental censorship policies. Therefor, to access websites like Facebook or Twitter we have to use proxies or VPNs. Proxies and VPNs have their own problems here and are not reliable solutions indeed. The issue becomes more complicated when it comes to mobile phone world; for example to access Twitter on my iPhone I have to connect to my VPN first and then open my Twitter client and it's really exhausting and painful!
Yesterday, that Twitter announced official "Twitter for iPhone", I received an update on my iPhone that replaced Tweetie 2 with the new official app and as soon as I opened the new app it asked for my Twitter username and password; one interesting point which I noticed was a proxy setting section that let users use a different proxy API other than Twitter official API. Soon after this, Pedram came up with a solution in his mind! His suggesting solution was twip. twip stands for Twitter + Proxy + PHP and is a free Twitter API proxy in PHP that let you create your very own proxy API on your desired domain name and use it instead of Twitter original API. In my case it was great because I could use it in on my iPhone and now I'm able to read tweets and update it without a VPN!
All you need to setup your proxy API on your domain are
- apache with mod_rewrite enabled
- >=PHP-5.2.4 with curl enabled (it may work with <5.2.4, but I only tested it on 5.2.4 :-) )
- zlib support if you want the gzip compression work
Then you should download twip and extract it in a folder on your web server (even root) and define it as your proxy API in Twitter for iPhone (or any other application which supports proxy API settings). At least you get rid of Twitter censorship in countries like Iran! I wish same solutions for Facebook, etc. ;-)
After setting this up successfully, I was thinking if there is any desktop Twitter client with the same functionality (to let the end user set his own proxy API) but unfortunately didn't find anything. So, do you know any? Tell me in the comments!
UPDATE: Thanks (!) to our friends at Google Code which have blocked all Iranian IPs, you have to use a proxy or VPN to download Twip from Iran! So I uploaded both available versions of Twip here. Go get it!
A documentary about Mohammadreza Shajarian on BBC Persian
Mohammadreza Shajarian is currently the most prominent traditional music singer in Iran. He is very popluar among Iranian people of all ages because of his magical voice and music and also his beliefs in freedom and liberty. He has been always alongside the Iraninan people and never allowed the powers, either the former Shah of Iran or the current Islamic Republic, use his music to achieve their political goals.
At the time of Bam earthquake disaster, he did his best to hold concerts and perform many other cultural activities to help the poor people who had lost everything in that quake.
After the 2009 rigged presidential election in Iran, he recored and released a song titled "Language of Fire" in protest to what was happening in Iran.
By the way, this is Mohammadreza Shajarian's official website: delawaz.com
BBC Persian has recently broadcasted an almost one hour documentary about the maestro; if you know Persian language don't miss this.
Help Team Hanselman Fight Diabetes
It's never too late to spread the word of humanity! I think it's even better to talk about it now because the flood of tweets and blog posts on Scott's action was only on the day he wrote his blog post on this. So after a while, I talk about it again.
Fortunately, neither me nor any of my family members are diabetic. I'm thankful for this because after reading Scott Hanselman's post about a diabetic's problems in his/her life, now I can feel what painful days they can have.
Anyway, if you're a diabetic or not, we can help Team Hanselman. If you wanna know more about Team Hanselman and Diabetics Walk 2010 please read Scott's original post .
You can donate here. Everything is explained in Scott's post and there is no need to repeat all here. I feel this is the least thing I can do.
How to use Google Data API in ASP.NET MVC. Part 1 – Google Analytics
It's really amazing that Google let developers access and use its services data via GData easily. It's really easy to interact with services like Calendar, Analytics, Google Reader, Blogger, YouTube, etc. using GData.
There are also several libraries for languages and technologies to include and use in your project.
Recently I needed to use Google API in a project to interact with YouTube and Google Analytics in an ASP.NET MVC application. My scenario was not too complicated and so I decided to share my experience in two separate blog posts and you're reading the first one of this series: using GData to retrieve a websites' visitors statistics information which is monitored by Google Analytics.
As I mentioned before, my scenario was not complicated and I just wanted to retrieves total number of page views as well as today and yesterday's page views number. Ready? Here we go!
First of all you need to download GData .NET library from Google Code and add references to these assemblies in your project:
- Google.GData.Analytics.dll
- Google.GData.Client.dll
- Google.GData.Extensions.dll
UPDATE: I was working on my project two months ago and I forgot to mention in my post that Google Analytics is not yet officially a part of GData .NET library. Anyway you can download it from Google Code SVN or the easier, I uploaded it here and you can get it.
Next, we need an Action method that returns information which is retrieved from GData to pass to our View:
public ActionResult Stats()
{
string userName = ConfigurationManager.AppSettings["GoogleUsername"];
string passWord = ConfigurationManager.AppSettings["GooglePassword"];
string profileId = ConfigurationManager.AppSettings["GoogleAnalyticsProfileId"];
const string dataFeedUrl = "https://www.google.com/analytics/feeds/data";
var service = new AnalyticsService("WebSiteAnalytics");
service.setUserCredentials(userName, passWord);
var dataQuery = new DataQuery(dataFeedUrl)
{
Ids = profileId,
Metrics = "ga:pageviews",
Sort = "ga:pageviews",
GAStartDate = new DateTime(2010, 3, 1).ToString("yyyy-MM-dd"),
GAEndDate = DateTime.Now.ToString("yyyy-MM-dd")
};
var dataFeed = service.Query(dataQuery);
var totalEntry = dataFeed.Entries[0];
ViewData["Total"] = ((DataEntry)(totalEntry)).Metrics[0].Value;
dataQuery.GAStartDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
dataQuery.GAEndDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
dataFeed = service.Query(dataQuery);
var yesterdayEntry = dataFeed.Entries[0];
ViewData["Yesterday"] = ((DataEntry)(yesterdayEntry)).Metrics[0].Value;
dataQuery.GAStartDate = DateTime.Now.ToString("yyyy-MM-dd");
dataQuery.GAEndDate = DateTime.Now.ToString("yyyy-MM-dd");
dataFeed = service.Query(dataQuery);
var todayEntry = dataFeed.Entries[0];
ViewData["Today"] = ((DataEntry)(todayEntry)).Metrics[0].Value;
return PartialView(dataFeed.Entries);
}
Now, let me explain the code a little. To authenticate with GData you should pass Google Username (e.g.: myusername@gmail.com), Google Password and ProfileID of website which you want to access data. This ProfileID is in this format: ga:NNNNNNN and you can find this NNNNNNN number in query string when you're logged in to your Google Analytics dashboard.
Next you define the URL of data feed which is https://www.google.com/analytics/feeds/data. Next steps are straightforward enough to understand; you create an instance of AnalyticsService and pass credentials, then send a new DataQuery to AnalyticsService object providing your query information (in this case, PageViews, StartDate and EndDate). DataFeed result which is returned from the service is an array of informtion and in our case we need its first element. If you look at my code you see that we have repeated this process to retrieve yesterday and today statistics.
I have chosen the easiest way to pass data to View which is using ViewData dictionary collection; but you can create a Model class with properties you need and bind it to your view.
Our view to show data looks like this:
< %@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> Website Stats:
- Total: < %= ((Convert.ToInt32(ViewData["Total"]))).ToString("##,#")%>
- Yesterday: < %= Convert.ToInt32(ViewData["Yesterday"]).ToString("##,#")%>
- Today: < %= Convert.ToInt32(ViewData["Today"]).ToString("##,#")%>
It was a very simple sample of how to use GData to show Google Analytics data on your ASP.NET MVC powered website. I hope it helps you :-)
Next post in these series will show you how to use GData to interact with YouTube API and upload videos from your application and stream it to your visitors.
