I have spent the last few hours going over this exciting new API service Netflix has to offer, really great.
I am looking around for any .NET based (C# or VB) working sample projects that may be available around? Is that a possibility to get directed towards such a resource or one that may provide directions to how to get it done in .NET?
I've got it working in C#. I've got a basic object model for the queues using a combination of XPath and attribute mappings to build the model from the XML, and I'm using a 3rd-party OAuth library for the communication with the API.
Here's the OAuth implementation I'm using:
http://code.google.com/p/oauth-dot-net/
If you have any questions about how to get that to work, I might be able to provide a few tips.
I might also be willing to share the object model, but I just started it yesterday and only the queue portion is close to complete.
@shatteredarm If you don't mind posting the C# sample using oauth-dot-net I'd appreciate it. Can't quite get it to work yet. Email is pderksen AT yahoo.com if preferred.
First you have to create the service:
_getService = OAuthService.Create(
new Uri("http://api.netflix.com/oauth/request_token"),
new Uri("https://api-user.netflix.com/oauth/login"),
new Uri("http://api.netflix.com/oauth/access_token"),
"GET",
false,
string.Empty,
"HMAC-SHA1",
"1.0",
new OAuthConsumer("{APP_KEY}", "{SECRET}", "Netflix Queue Manager"));
Create properties for the tokens:
private IToken _requestToken;
private IToken _accessToken;
I abstracted the call out so I can theoretically grab any resource with this method:
private OAuthResource Get(string uri, NameValueCollection parameters)
{
OAuthRequest rq = OAuthRequest.Create(
new Uri(uri),
_getService,
RequestToken,
AccessToken); // Create the request
rq.OnReceiveAccessToken += new EventHandler<AccessTokenReceivedEventArgs>(rq_OnReceiveAccessToken);
OAuthResponse response = rq.GetResource(parameters); //get the response
if (response.HasProtectedResource)
{
return response.ProtectedResource;
}
else
{
RequestToken = response.Token; //if you got here, it means you only have the request token and need to direct the user to the login page.
throw new OAuthNotAuthorizedException();
}
}
I created this method to store the access token before it makes the request to the actual resource. I had to hack this implementation of OAuth because after receiving the OAuth token, it immediately requests the resource, but you need to get the access token before you have the actual UserID, which is required for the request. So, I stored the UserID at this point, and hacked the OAuth class so that it would allow me to change the RequestUri at this stage (out of the box, it only allows you to set that in the Create() call, at which point you might not know the UserId if it is the first try). I made it so that if you're requesting a user resource, you put {userid} in the part of the URI that requires it, and you then replace that later on. I actually have a glitch here though, as the "{" and "}" characters were encoded and replace currently doesn't work as it is.
void rq_OnReceiveAccessToken(object sender, AccessTokenReceivedEventArgs e)
{
AccessToken = e.AccessToken;
UserId = e.AdditionalParameters["user_id"];
OAuthRequest req = sender as OAuthRequest;
req.ResourceUri = new Uri(req.ResourceUri.AbsoluteUri.Replace("{userid}", UserId)); //TODO
}
Let me know if you need any more info to get started.
Oh, and I also added a method to build the authentication url to direct the user to:
public Uri AuthenticationUri
{
get
{
NameValueCollection parameters = new NameValueCollection();
parameters.Add("application_name", _getService.Consumer.FriendlyName);
parameters.Add("oauth_consumer_key", _getService.Consumer.Key);
return _getService.BuildAuthorizationUrl(RequestToken, parameters);
}
}
I'm doing this in a windows forms app, so I didn't add the callback url parameter, but you'd just do that the same way as the others.
To make a call to the API (assuming you have your service defined), you first create an OAuthRequest by calling OAuthRequest.Create. The parameters are the URI, the service, and the request and access token (which you should declare as type IToken and will be null at first).
You then call the GetResource method on the Request object, pass in a NameValueCollection object for the parameters (for example, search queries), and store the result in a OAuthResponse object.
There are two scenarios:
a) You're accessing an unprotected resource.
In this case, if you don't provide a Request Token, the GetResource method will behind the scenes get the request token, and then get the resource. If you do provide it, it can skip that extra trip. In this case, the HasProtectedResource property returns true, meaning you have the data you need, which is in the ProtectedResource property (type OAuthResource).
b) You're accessing a protected resource.
Here, if you don't provide any tokens, it will first go get the request token, and find that the resource is protected, and then return. As long as the access token is unavailable (i.e., user has not given application permission), the GetResource() method will return with the HasProtectedResource property set to false. At this point, you want to store the request token and then send some sort of notification that the user needs to authorize the application, as in my above code. After the user authorizes the application, instead of returning with the HasProtectedResource set to false, it will instead then grab the access token, followed by the resource. You'll also want to note that most of the protected resources require a UserID in the URL, which isn't given to you until after you get the access token. You'll want to create an event handler that handles OnReceiveAccessToken, and the UserId will be given to you in the AdditionalParameters hashtable in the event arguments. Since you didn't have the UserID when you defined the URI, you'll either have to hack the OAuth library to allow you to reset the URI, or handle the WebException and retry the request with the URI set properly from the beginning.
To actually get the data, wrap a StreamReader around the response stream and dump it in a string, like so:
return new StreamReader(resource.GetResponseStream()).ReadToEnd();
Here's some code to get a user's queue:
NameValueCollection parameters = new NameValueCollection();
parameters.Add("start_index", startIndex.ToString());
parameters.Add("max_results", "25");
if (UserId == null || UserId == string.Empty){
try{
Get("http://api.netflix.com/users/asdf/queues/disc/available", parameters) //I've already posted the code for this above
} catch (WebException) {}
}
return new StreamReader(GetUserResource(string.Format("http://api.netflix.com/users/{0}/queues/disc/available",UserId), parameters).GetResponseStream()).ReadToEnd();
After jumping out to validate the account: System.Diagnostics.Process.Start(this.AuthenticationUri.ToString());
I never seem to get the access token as the event never fires:
rq.OnReceiveAccessToken += new EventHandler<AccessTokenReceivedEventArgs>(rq_OnReceiveAccessToken);
I'd suggest stepping through the code (if you built the module on your own machine, you should be able to step into it). Are you trying to hit a protected resource (like a queue)? If it's an unprotected resource, like an index or search, you won't need or get an access token. Also, make sure you're sending in the same Request Token you got from the original call before the validation.
Only after the user has gone to the Netflix URL and authorized the application. Have you successfully done that?
If so, are you sending in the same Request Token you received after the first call? Also, if you've already received an access token, it won't go back for another one... So OnReceiveAccessToken should only be fired once, which will be the first call after the user authorizes.
public Netflix()
{
this.service = OAuthService.Create(
new Uri("http://api.netflix.com/oauth/request_token"),
new Uri("https://api-user.netflix.com/oauth/login"),
new Uri("http://api.netflix.com/oauth/access_token"),
"GET",
false,
string.Empty,
"HMAC-SHA1",
"1.0",
new OAuth.Net.Components.OAuthConsumer(this.appKey, this.sectret, ""));
1) Does your AuthenticationUri property set the application_name and oauth_consumer_key properties?
2) It looks like you're getting the resource in the constructor. I'm assuming _requestToken and _accessToken aren't static, in which case you'll lose the RequestToken after the call. It's probably better to have one instance of your Netflix class and wrap the call to /recommendations in an instance method.
I have something like this:
public NetflixService(){
//Create OAuthService instances
/* SNIP */
}
public string UpdateInstantWatchQueue(string titleRef, int newPosition, long etag)
{
NameValueCollection parameters = new NameValueCollection();
parameters.Add("title_ref", titleRef);
parameters.Add("position", newPosition.ToString());
parameters.Add("etag", etag.ToString());
return new StreamReader(Post(string.Format("http://api.netflix.com/users/{0}/queues/instant", UserId), parameters).GetResponseStream()).ReadToEnd();
}
Then, in a separate class, you might have:
NetflixService service = new NetflixService();
try{
return service.UpdateInstantWatchQueue(item.titleLink.href, 0, queue.etag);
}catch (OAuthNotAuthorizedException){
Process.Start(@"C:\Program Files\Opera\opera.exe", service.AuthenticationUri);
}
Basically, I think the problem might be that you're losing the request token. You have it stored in an instance variable, but you're creating a separate instance for each call.
Hey, I've decided that I'm almost 110% sure I'm not going to actually release an application outside of my own personal use, so I'm going to put what I build up on Codeplex as a C# library that anyone can consume. Maybe it'll save everybody effort if everybody doesn't have to reinvent the wheel. ;)
I finally get the access token after doing a couple "fake" calls (after the app has returned from the website authorization) and then forming a good request using the tokens gained from the requests.
Although, the requests now work to the netflix service, they all return with zero data except for the url_template element.
Example:
<recommendations>
<url_template>http://api.netflix.com/users/R1cRM9mTWtW6i_UZjJ_AVvqG7EjpuDXR4QIXDIuikelEw-/recommendations?{-join|&|start_index|max_results}</url_template>
</recommendations>
I wonder if it is because the access token status is Unknown?
There must be some bugs in the OAuth.NET implementation.
Anyway, for some reason the access token will not work in future requests if you do not first get the access token using a URL request that has non-protected data.
I posted all my source code here:
http://code.google.com/p/nfapi/source/browse/
Obviously the functions I've implemented so far are limited, but the plumbing is pretty stable now.
It looks like it's requiring an access token for that resource. I'm not sure if that's a problem with OAuth.NET, the Netflix API, or if it's intended to be that way, but it's working fine for me if I provide an access token.
Hi ShatteredArm, I have the same problem exception...
Is it possible that Netflix changed something since one month ago? Or is it really a OAuth.NET issue?
Hello All,
I have spent the last few hours going over this exciting new API service Netflix has to offer, really great.
I am looking around for any .NET based (C# or VB) working sample projects that may be available around? Is that a possibility to get directed towards such a resource or one that may provide directions to how to get it done in .NET?
thank you,
muvieflicks
Message edited by muvieflicks 3 months ago
Tags
ShatteredArm – 3 years ago
I've got it working in C#. I've got a basic object model for the queues using a combination of XPath and attribute mappings to build the model from the XML, and I'm using a 3rd-party OAuth library for the communication with the API.
Here's the OAuth implementation I'm using:
http://code.google.com/p/oauth-dot-net/
If you have any questions about how to get that to work, I might be able to provide a few tips.
I might also be willing to share the object model, but I just started it yesterday and only the queue portion is close to complete.
gproano – 3 years ago
i'm using the simple oauth.cs base class available linked to from the OAuth page, I extend it and then do something simple like this:
string url = null;
string reqParam = null;
string sig = this.GenerateSignature(new Uri(requestTokenUrl), Key, secret, null, null, "GET", this.GenerateTimeStamp(), this.GenerateNonce(), out url, out reqParam);
string encoded = reqParam + "&oauth_signature=" + this.UrlEncode(sig);
token = Utility.Query(url +"?"+encoded);
pderksen – 3 years ago
@shatteredarm If you don't mind posting the C# sample using oauth-dot-net I'd appreciate it. Can't quite get it to work yet. Email is pderksen AT yahoo.com if preferred.
ShatteredArm – 3 years ago
First you have to create the service:
_getService = OAuthService.Create(
new Uri("http://api.netflix.com/oauth/request_token"),
new Uri("https://api-user.netflix.com/oauth/login"),
new Uri("http://api.netflix.com/oauth/access_token"),
"GET",
false,
string.Empty,
"HMAC-SHA1",
"1.0",
new OAuthConsumer("{APP_KEY}", "{SECRET}", "Netflix Queue Manager"));
Create properties for the tokens:
private IToken _requestToken;
private IToken _accessToken;
I abstracted the call out so I can theoretically grab any resource with this method:
private OAuthResource Get(string uri, NameValueCollection parameters)
{
OAuthRequest rq = OAuthRequest.Create(
new Uri(uri),
_getService,
RequestToken,
AccessToken); // Create the request
rq.OnReceiveAccessToken += new EventHandler<AccessTokenReceivedEventArgs>(rq_OnReceiveAccessToken);
OAuthResponse response = rq.GetResource(parameters); //get the response
if (response.HasProtectedResource)
{
return response.ProtectedResource;
}
else
{
RequestToken = response.Token; //if you got here, it means you only have the request token and need to direct the user to the login page.
throw new OAuthNotAuthorizedException();
}
}
I created this method to store the access token before it makes the request to the actual resource. I had to hack this implementation of OAuth because after receiving the OAuth token, it immediately requests the resource, but you need to get the access token before you have the actual UserID, which is required for the request. So, I stored the UserID at this point, and hacked the OAuth class so that it would allow me to change the RequestUri at this stage (out of the box, it only allows you to set that in the Create() call, at which point you might not know the UserId if it is the first try). I made it so that if you're requesting a user resource, you put {userid} in the part of the URI that requires it, and you then replace that later on. I actually have a glitch here though, as the "{" and "}" characters were encoded and replace currently doesn't work as it is.
void rq_OnReceiveAccessToken(object sender, AccessTokenReceivedEventArgs e)
{
AccessToken = e.AccessToken;
UserId = e.AdditionalParameters["user_id"];
OAuthRequest req = sender as OAuthRequest;
req.ResourceUri = new Uri(req.ResourceUri.AbsoluteUri.Replace("{userid}", UserId)); //TODO
}
Let me know if you need any more info to get started.
ShatteredArm – 3 years ago
Oh, and I also added a method to build the authentication url to direct the user to:
public Uri AuthenticationUri
{
get
{
NameValueCollection parameters = new NameValueCollection();
parameters.Add("application_name", _getService.Consumer.FriendlyName);
parameters.Add("oauth_consumer_key", _getService.Consumer.Key);
return _getService.BuildAuthorizationUrl(RequestToken, parameters);
}
}
I'm doing this in a windows forms app, so I didn't add the callback url parameter, but you'd just do that the same way as the others.
thirteen23 – 3 years ago
Hi, I am also looking for some help...
I have the OAuth code working (at least creating the OAuthService), but sort of lost from that point on.
I can't figure out the order/initialization of the access token, request token, and login from Netflix site, etc...
Just looking for more complete code, if possible. Thanks-
ryan at thirteen23 dott com
Ryan Dawson
thirteen23
ShatteredArm – 3 years ago
Here's how the OAuth.net api works:
To make a call to the API (assuming you have your service defined), you first create an OAuthRequest by calling OAuthRequest.Create. The parameters are the URI, the service, and the request and access token (which you should declare as type IToken and will be null at first).
You then call the GetResource method on the Request object, pass in a NameValueCollection object for the parameters (for example, search queries), and store the result in a OAuthResponse object.
There are two scenarios:
a) You're accessing an unprotected resource.
In this case, if you don't provide a Request Token, the GetResource method will behind the scenes get the request token, and then get the resource. If you do provide it, it can skip that extra trip. In this case, the HasProtectedResource property returns true, meaning you have the data you need, which is in the ProtectedResource property (type OAuthResource).
b) You're accessing a protected resource.
Here, if you don't provide any tokens, it will first go get the request token, and find that the resource is protected, and then return. As long as the access token is unavailable (i.e., user has not given application permission), the GetResource() method will return with the HasProtectedResource property set to false. At this point, you want to store the request token and then send some sort of notification that the user needs to authorize the application, as in my above code. After the user authorizes the application, instead of returning with the HasProtectedResource set to false, it will instead then grab the access token, followed by the resource. You'll also want to note that most of the protected resources require a UserID in the URL, which isn't given to you until after you get the access token. You'll want to create an event handler that handles OnReceiveAccessToken, and the UserId will be given to you in the AdditionalParameters hashtable in the event arguments. Since you didn't have the UserID when you defined the URI, you'll either have to hack the OAuth library to allow you to reset the URI, or handle the WebException and retry the request with the URI set properly from the beginning.
To actually get the data, wrap a StreamReader around the response stream and dump it in a string, like so:
return new StreamReader(resource.GetResponseStream()).ReadToEnd();
Here's some code to get a user's queue:
NameValueCollection parameters = new NameValueCollection();
parameters.Add("start_index", startIndex.ToString());
parameters.Add("max_results", "25");
if (UserId == null || UserId == string.Empty){
try{
Get("http://api.netflix.com/users/asdf/queues/disc/available", parameters) //I've already posted the code for this above
} catch (WebException) {}
}
return new StreamReader(GetUserResource(string.Format("http://api.netflix.com/users/{0}/queues/disc/available",UserId), parameters).GetResponseStream()).ReadToEnd();
thirteen23 – 3 years ago
Thanks for the response...
After jumping out to validate the account: System.Diagnostics.Process.Start(this.AuthenticationUri.ToString());
I never seem to get the access token as the event never fires:
rq.OnReceiveAccessToken += new EventHandler<AccessTokenReceivedEventArgs>(rq_OnReceiveAccessToken);
From your code above. Any ideas?
Thanks-
ShatteredArm – 3 years ago
I'd suggest stepping through the code (if you built the module on your own machine, you should be able to step into it). Are you trying to hit a protected resource (like a queue)? If it's an unprotected resource, like an index or search, you won't need or get an access token. Also, make sure you're sending in the same Request Token you got from the original call before the validation.
thirteen23 – 3 years ago
Yeah, weird...
OAuthResource resource = this.Get(@"http://api.netflix.com/users/" + this.userID + @"/recommendations", new NameValueCollection());
Does the OnReceiveAccessToken event fire right away for you?
ShatteredArm – 3 years ago
Only after the user has gone to the Netflix URL and authorized the application. Have you successfully done that?
If so, are you sending in the same Request Token you received after the first call? Also, if you've already received an access token, it won't go back for another one... So OnReceiveAccessToken should only be fired once, which will be the first call after the user authorizes.
thirteen23 – 3 years ago
See if you find any errors in my code, thanks:
public Netflix()
{
this.service = OAuthService.Create(
new Uri("http://api.netflix.com/oauth/request_token"),
new Uri("https://api-user.netflix.com/oauth/login"),
new Uri("http://api.netflix.com/oauth/access_token"),
"GET",
false,
string.Empty,
"HMAC-SHA1",
"1.0",
new OAuth.Net.Components.OAuthConsumer(this.appKey, this.sectret, ""));
OAuthResource resource = this.Get(@"http://api.netflix.com/users/" + this.userID + @"/recommendations",
new NameValueCollection());
}
private OAuthResource Get(string uri, NameValueCollection parameters)
{
OAuthRequest rq = OAuthRequest.Create(
new Uri(uri),
this.service,
_requestToken,
_accessToken);
rq.OnReceiveAccessToken += new EventHandler<AccessTokenReceivedEventArgs>(rq_OnReceiveAccessToken);
OAuthResponse response = rq.GetResource(parameters);
if (response.HasProtectedResource)
{
return response.ProtectedResource;
}
else
{
_requestToken = response.Token;
System.Diagnostics.Process.Start(this.AuthenticationUri.ToString());
return null;
}
}
void rq_OnReceiveAccessToken(object sender, AccessTokenReceivedEventArgs e)
{
_accessToken = e.AccessToken;
this.userID = e.AdditionalParameters["user_id"];
}
ShatteredArm – 3 years ago
1) Does your AuthenticationUri property set the application_name and oauth_consumer_key properties?
2) It looks like you're getting the resource in the constructor. I'm assuming _requestToken and _accessToken aren't static, in which case you'll lose the RequestToken after the call. It's probably better to have one instance of your Netflix class and wrap the call to /recommendations in an instance method.
I have something like this:
public NetflixService(){
//Create OAuthService instances
/* SNIP */
}
public string UpdateInstantWatchQueue(string titleRef, int newPosition, long etag)
{
NameValueCollection parameters = new NameValueCollection();
parameters.Add("title_ref", titleRef);
parameters.Add("position", newPosition.ToString());
parameters.Add("etag", etag.ToString());
return new StreamReader(Post(string.Format("http://api.netflix.com/users/{0}/queues/instant", UserId), parameters).GetResponseStream()).ReadToEnd();
}
Then, in a separate class, you might have:
NetflixService service = new NetflixService();
try{
return service.UpdateInstantWatchQueue(item.titleLink.href, 0, queue.etag);
}catch (OAuthNotAuthorizedException){
Process.Start(@"C:\Program Files\Opera\opera.exe", service.AuthenticationUri);
}
Basically, I think the problem might be that you're losing the request token. You have it stored in an instance variable, but you're creating a separate instance for each call.
ShatteredArm – 3 years ago
Hey, I've decided that I'm almost 110% sure I'm not going to actually release an application outside of my own personal use, so I'm going to put what I build up on Codeplex as a C# library that anyone can consume. Maybe it'll save everybody effort if everybody doesn't have to reinvent the wheel. ;)
thirteen23 – 3 years ago
I finally get the access token after doing a couple "fake" calls (after the app has returned from the website authorization) and then forming a good request using the tokens gained from the requests.
Although, the requests now work to the netflix service, they all return with zero data except for the url_template element.
Example:
<recommendations>
<url_template>http://api.netflix.com/users/R1cRM9mTWtW6i_UZjJ_AVvqG7EjpuDXR4QIXDIuikelEw-/recommendations?{-join|&|start_index|max_results}</url_template>
</recommendations>
I wonder if it is because the access token status is Unknown?
thirteen23 – 3 years ago
An update...
There must be some bugs in the OAuth.NET implementation.
Anyway, for some reason the access token will not work in future requests if you do not first get the access token using a URL request that has non-protected data.
ShatteredArm – 3 years ago
Eh, I don't know about that. I've been able to get it just fine without accessing a URL with non-protected data.
ShatteredArm – 3 years ago
I posted all my source code here:
http://code.google.com/p/nfapi/source/browse/
Obviously the functions I've implemented so far are limited, but the plumbing is pretty stable now.
Enjoy!
pderksen – 3 years ago
Thanks Shattered! I'll check it out soon.
Stephen Cook – 3 years ago
i keep getting a "NFAPI.OAuthNotAuthorizedException" error.. all i am trying to do is search for a catalog title
ShatteredArm – 3 years ago
It looks like it's requiring an access token for that resource. I'm not sure if that's a problem with OAuth.NET, the Netflix API, or if it's intended to be that way, but it's working fine for me if I provide an access token.
mikey – 3 years ago
What resource are you trying to access, ShatteredArm?
ShatteredArm – 3 years ago
http://api.netflix.com/catalog/titles
Like I said, it could be a problem with OAuth.NET, although I do recall having it working a month or so ago.
mfmanca – 3 years ago
Hi ShatteredArm, I have the same problem exception...
Is it possible that Netflix changed something since one month ago? Or is it really a OAuth.NET issue?