Thursday, August 20, 2015

Publish Posts on Blogger.com - API v3.0

In January I wrote a post about how to publish posts automatically on Blogger.com. This however used for that the API v2.0, which is now deprecated, therefore I here want to show how to do this with the current API v3.0.
Unfortunately I did not find a way (and I do not know if there is one) to really publish the posts without the user having to interact, now he has to log in in the browser and copy some code.
From a high level view the procedure in this version is as follows:
Via the Google Developer Console a new project has to be created and the Blogger API has to be enabled. Information about this step and the general usage of the API can be found here.
Then, to be able to use the API, we need to authenticate via OAuth 2.0. For this, we have to send a request to Google. We can do so by calling a specific URL in the browser, as parameters we specify amongst others the ID of our project, the scope for which we want to use the access etc. The user then logs in in the browser and a authorization code is presented. This code the program then sends via an HTTP request to Google and we now get back a token. With this we can eventually call the API and thus publish posts on Blogger. This procedure is decribed here.

After this high level overview, let us come to concrete implementation: First we create a new project in the Google Developer Console. Then we look for the API Blogger API v3 in the menu APIs and enable it.
Now, in our C# program, we first have to call an URL to do our initial request. The needed URL is https://accounts.google.com/o/oauth2/auth. One parameter we pass over is scope, which describes for which application we want to authenticate, for this we send https://www.googleapis.com/auth/blogger. The next parameter is the redirect URL (redirect_uri), which determines to where the answer is send. When setting this to urn:ietf:wg:oauth:2.0:oob the answer is shown in the opened browser. Via response_type=code we determine to get a code back. As the last parameter we set client_id to the ID of our created project in the Google Developer Console. This is NOT the Project ID which can be found on the mainpage, but to get the client id one has to navigate to APIs & auth - Credentials and then click on (if not already done) Add credentials - OAuth 2.0 client ID. Then we select Other (because we are designing a native application) and click on Create - then we get the client id.
All in all the URL to be called should look like this:

https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/blogger&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&client_id=client-id


We simply use Process.Start on the URL to start the default browser with it. In this, the user is presented with a login and consent screen. If he clicks accept, a success code is presented. We copy this.
With the code, we can get an access token for using the Blogger API. For this we now have to do a HTTP Post Request. The URL to be called is https://www.googleapis.com/oauth2/v3/token, as parameters we have to send the obtained code (code), the client id (client_id), the redirect url (redirect_uri, same as before), the grant type (grant_type=authorization_code - describes how we want to authenticate) and the client secret (client_secret). The latter we can see when clicking on the client id under Credentials.
With the method HTTPPost() presented in the linked post this looks as follows:

            string Code = "code=" + Code1 + "&";
            string ID = "client_id=id&";
            string uri = "redirect_uri=urn:ietf:wg:oauth:2.0:oob&";
            string grant = "grant_type=authorization_code&";
            string secret = "client_secret=secret";

            string Code2 = HTTPPost("https://www.googleapis.com/oauth2/v3/token", Code + ID + uri + grant + secret);

We read out the answer of the server since this contains (if successful) the access token. The answer is given in the JSON format, we use the library Newtonsoft.Json to interpret this. Maybe I will write a post about the library, for now I just refer to this post where it is also used.
Thus we obtain the access token via the following code, where AccessToken is a custom class with the desired attribute:

AccessToken JsonAccToken = (AccessToken)JsonConvert.DeserializeObject(Code2, typeof(AccessToken));
string StrAccToken = JsonAccToken.access_token;
With this token we can now use the API to publish posts on Blogger. We use a WebRequest to send the correct POST request to the Blogger server. As the target adress we select https://www.googleapis.com/blogger/v3/blogs/.
First we set the correct content type, select the authentication header etc:

var http = (HttpWebRequest)WebRequest.Create(new Uri("https://www.googleapis.com/blogger/v3/blogs/" + sid + "/posts/"));
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "POST";
http.Headers.Add("Authorization", "Bearer " + token);

sid is the ID of the blog to which we want to publish. Next we describe the post in JSON format, for that we first write it as a string and then convert it.
var vm = new { kind = "blogger#post", blog = new { id = sid }, title = stitle, content = scontent };
var dataString = JsonConvert.SerializeObject(vm);
string parsedContent = dataString;

In the code stitle denotes the title of the post, scontent the content (which is expected in the HTML format).
Eventually we upload this via the WebRequest.
The complete code looks as follows:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Net;
using System.IO;
using Newtonsoft.Json;

namespace Blogger
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/blogger&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&client_id=client-id");
        }

        private string HTTPPost(string url, string postparams)
        {
            string responseString = "";

            // performs the desired http post request for the url and parameters
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            // request.CookieContainer = Cookie; // explicitely use the cookiecontainer to save the session

            string postData = postparams;
            byte[] data = Encoding.UTF8.GetBytes(postData);

            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = data.Length;

            using (var stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

            var response = (HttpWebResponse)request.GetResponse();

            responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

            return responseString;

        }

        private void Form1_Click(object sender, EventArgs e)
        {
            string Code = "code=" + textBox1.Text + "&";
            string ID = "client_id=client-id&";
            string uri = "redirect_uri=urn:ietf:wg:oauth:2.0:oob&";
            string grant = "grant_type=authorization_code&";
            string secret = "client_secret=secret";

            string Code2 = HTTPPost("https://www.googleapis.com/oauth2/v3/token", Code + ID + uri + grant + secret);

            AccessToken JsonAccToken = (AccessToken)JsonConvert.DeserializeObject(Code2, typeof(AccessToken));
            string StrAccToken = JsonAccToken.access_token;

            JSONPublish(BlogID, "Testpost", "This is a <b>Test</b>.", StrAccToken);
        }

        private void JSONPublish(string sid, string stitle, string scontent, string token)
        {
            var http = (HttpWebRequest)WebRequest.Create(new Uri("https://www.googleapis.com/blogger/v3/blogs/" + sid + "/posts/"));
            http.Accept = "application/json";
            http.ContentType = "application/json";
            http.Method = "POST";
            http.Headers.Add("Authorization", "Bearer " + token);

            var vm = new { kind = "blogger#post", blog = new { id = sid }, title = stitle, content = scontent };
            var dataString = JsonConvert.SerializeObject(vm);
            string parsedContent = dataString;

            Byte[] bytes = Encoding.UTF8.GetBytes(parsedContent);

            Stream newStream = http.GetRequestStream();
            newStream.Write(bytes, 0, bytes.Length);
            newStream.Close();

            var response = http.GetResponse();

            var stream = response.GetResponseStream();
            var sr = new StreamReader(stream);
            var content = sr.ReadToEnd();
        }

        public class AccessToken
        {
            [JsonProperty(PropertyName = "access_token")]
            public string access_token { get; set; }
        }
    }
}

27 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. while i am running this code it returns an error for unauthorized user. i am doing please tell me

    ReplyDelete
    Replies
    1. If you follow all steps from the post it should work. Maybe you forgot to activate the Blogger API for your project in the Google Developer console, you logged in with a different user name .. There could be numerous reasons. Please double check the post.

      Delete
    2. can u please send me the sample code for how to post the string to blogger and how to active my blogger api for in my project ,give steps for how to active my blogger api

      Delete
  5. how can i retrive the grant form blogger account.give me a steps to retrive grant id.

    ReplyDelete
    Replies
    1. Hello, this is all described in the post, please read carefully. Where is the exact problem, what is not working?

      Delete
  6. I don`t know what type of values give in it string grant = "grant_type=authorization_code&";
    what values I give with it grant_type I am Following your blog but it gives ma a error of bad request The remote server returned an error: (400) Bad Request

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Ok.. i got "grant_type=authorization_code" by clicks accept, a success code is presented, it is used for "authorization_code" it's working when i login with my Client_ID, Secret User account. But if another person who didn't knows my userid, password, how can they post text into my blogger..Old API code working like that, any one can post into my blogger, but that possibility is not in this API 3.0, is there any possibility for that..please help or you can contact me "deviprasad987@gmail.com", "7036123270"

    ReplyDelete
  9. Oh, Thank you very much, @Oliver S
    I have tried a few hour to understand how to authenticate with google and go to blogger section til i saw your post... Very nice, and easy to understand... Thanks for all hard work, mate.

    ReplyDelete
  10. Thanks for the tutorial. Its easy to understand compared to other oAuth tutorial.

    But I have some issue on this line:
    var response = http.GetResponse();

    The exception is
    The remote server returned an error: (403) Forbidden.

    Could you help me on this?

    ReplyDelete
    Replies
    1. It's turns out that I'm not enable the blogger api yet!
      now it works for me.
      Thank you

      Delete
  11. Thanks for the tutorial. I try wpf application .works

    ReplyDelete
  12. Thank You,
    its best of code for Send Post to Bloger

    ReplyDelete
  13. Great Post !! But how can we upload and insert images into our blogger posts?

    ReplyDelete
  14. This comment has been removed by a blog administrator.

    ReplyDelete
  15. nic post
    http://mkniit.blogspot.in

    ReplyDelete
  16. Any idea how to add Labels to the post?

    ReplyDelete

  17. Given so much information in it. its very useful .perfect explanation about Dot net framework.Thanks for your valuable information. Dot Net Training in chennai | Dot Net Training in velachery

    ReplyDelete
  18. It is really a great work and the way in which u r sharing the knowledge is excellent.
    Thanks for helping me to understand basic concepts. As a beginner in Dot Net programming your post help me a lot.Thanks for your informative article.
    dot net training in velachery | dot net training in chennai

    ReplyDelete
  19. Thanks for your tutorial, but I would like to know, is another way to automatically post to blogger? If everytime need to start the browser and copy the code in the application, it cannot run in my task scheduler. Thanks.

    ReplyDelete
  20. I want to thank you for writing this article.This is great Article for me. It also more very informative & awesome. I expect more articles from you in future...
    Hire PHP developer in India

    ReplyDelete