Introduction
Recently I was asked to extend the default MonoX functionality by pushing blogs posts from a MonoX-based project to BlogSpot.
Blogger is a free tool that allows you to create personal blogs. These blogs are hosted for free on blogspot.com. BlogSpot has a basic WYSIWYG editor and a rudimantary support for tags. MonoX, on the other hand, supports categories, multiple blogs, has a feature rich WYSIWYG editor, and more.
Since MonoX has more features than BlogSpot, we could only push the blog title, content and the tags into it.
Using the API
You need to download the Google Data API from here. Please make sure that you have the version 2.1 version or later. Older versions have a bug related to tags which in turn does not allow you to properly sync tags.
When you install the Google Data API you can find your references in the X:\Program Files\Google\Google Data API SDK directory. You will need the Google.GData.Client.dll, Google.GData.Extensions.dll and Google.GData.Blogger.dll.
Authorization
There are a couple of ways to connect with someone’s BlogSpot account. You can ask the user for his username and password, or use OAuth 2.0. In this sample we're going to use the simple username and password approach. I highly recommend that you use the OAuth 2.0 approach in the real-world scenarios. My colleagues explained this procedure in more depth so you can read their posts for more information: Using Google Photos API in ASP.NET and Using Google Docs API in ASP.NET.
Using the API
Pushing or updating a blog post
For my implementation I've created a simple data transfer object (DTO) to handle the Blogger data. Here is how it looks:
public
string
BlogSelfUrl {
get
;
private
set
; }
public
string
Title {
get
;
set
; }
public
string
Content {
get
;
set
; }
public
List<
string
> Tags {
get
;
set
; }
public
bool
IsPublished {
get
;
set
; }
public
BlogPostDTO()
:
this
(
string
.Empty)
{
}
public
BlogPostDTO(
string
blogId)
{
this
.BlogSelfUrl = blogId;
}
Please note the BlogSelfUrl, which is basically a BlogId. Using it, you can fetch an existing blog entry or delete a blog entry. Now let's take a look at the actual method which posts or updates a blog post:
public
bool
PostOrUpdateBlogPost(BlogPostDTO blog,
bool
isUpdate)
{
if
(blog !=
null
)
{
var service =
new
Google.GData.Client.Service(blogKeyName,
this
.BlogName);
service.Credentials =
new
GDataCredentials(
this
.Username,
this
.Password);
AtomEntry newPost =
null
;
if
(isUpdate)
{
try
{
newPost = service.Get(blog.BlogSelfUrl);
newPost.Categories.Clear();
}
catch
(Exception ex)
{
// error handling goes here
return
false
;
}
}
else
{
newPost =
new
AtomEntry();
}
newPost.IsDraft = !blog.IsPublished;
if
(blog.Tags !=
null
&& blog.Tags.Count > 0)
{
foreach
(var tag
in
blog.Tags)
{
AtomCategory atomCategory =
new
AtomCategory();
atomCategory.Scheme = blogTagScheme;
atomCategory.Term = tag;
newPost.Categories.Add(atomCategory);
}
}
newPost.Title.Text = blog.Title;
newPost.Content =
new
AtomContent();
newPost.Content.Content = blog.Content;
newPost.Content.Type = blogHTMLType;
try
{
if
(!isUpdate)
{
Uri blogPostUri =
this
.SelectUserBlog(service);
newPost = service.Insert(blogPostUri, newPost);
}
else
{
newPost = newPost.Update();
}
return
newPost !=
null
;
}
catch
(Exception ex)
{
// error handling goes here
}
}
return
false
;
}
Deleting a blog post
Deleting a blog post requires you to store the BlogSelfUrl for later usage as we can use it as a BlogId. Deleting a blog is also a very straightforward process; here is how you can do that:
public
bool
DeleteBlogPost(
string
blogId)
{
var service =
new
Google.GData.Client.Service(blogKeyName,
this
.BlogName);
service.Credentials =
new
GDataCredentials(
this
.Username,
this
.Password);
bool
isDeleted =
false
;
if
(!
string
.IsNullOrWhiteSpace(blogId))
{
try
{
Uri uri =
new
Uri(blogId);
service.Delete(uri);
isDeleted =
true
;
}
catch
(Exception ex)
{
// error handling goes here
isDeleted =
false
;
}
}
return
isDeleted;
}
Fetching a list of blog posts
We can also fetch a list of blog posts. The BloggerAgent which you can download at the bottom of this post allows you to specify the amount of blog posts you want to fetch from the BlogSpot. Here is the code which fetches a list of blog posts:
public
List<BlogPostDTO> GetBlogList()
{
var service =
new
Google.GData.Client.Service(blogKeyName,
this
.BlogName);
service.Credentials =
new
GDataCredentials(
this
.Username,
this
.Password);
Uri blogPostUri =
null
;
try
{
blogPostUri =
this
.SelectUserBlog(service);
}
catch
(Exception ex)
{
// error handling goes here
return
new
List<BlogPostDTO>();
}
List<BlogPostDTO> blogs =
new
List<BlogPostDTO>();
FeedQuery query =
new
FeedQuery();
query.Uri = blogPostUri;
query.NumberToRetrieve =
this
.NumberOfBlogsToShow;
AtomFeed feed =
null
;
try
{
feed = service.Query(query);
}
catch
(Exception ex)
{
// error handling goes here
return
new
List<BlogPostDTO>();
}
foreach
(AtomEntry entry
in
feed.Entries)
{
BlogPostDTO blog =
new
BlogPostDTO(entry.SelfUri.Content);
if
(entry.Categories !=
null
&& entry.Categories.Count > 0)
{
blog.Tags =
new
List<
string
>();
foreach
(var item
in
entry.Categories)
{
blog.Tags.Add(item.Term);
}
}
blog.Title = entry.Title.Text;
blog.Content = entry.Content.Content;
blog.IsPublished = !entry.IsDraft;
blogs.Add(blog);
}
return
blogs;
}
MonoX implementation
Let's see what would be required to push blogs posted from the MonoX platform into the BlogSpot. The following scenario applies to projects which are built on top of MonoX. To push a blog post to the BlogSpot we need to override several MonoX controls and listen for the BlogPostEdit control's BlogPostSaved event. From this point on, it will be very easy to adapt the code explained previously in your custom MonoX projects.
1. You need to inherit the BlogContainer.ascx Web part and copy its markup; we also need to listen for the BlogPostSaved event. Here is how we can do that:
protected
override
void
OnInit(EventArgs e)
{
base
.OnInit(e);
blogPostEdit.BlogPostSaved +=
new
EventHandler(blogPostEdit_BlogPostSaved);
}
void
blogPostEdit_BlogPostSaved(
object
sender, EventArgs e)
{
var postedBlog = MonoSoftware.MonoX.Repositories.BlogRepository.GetInstance().GetBlogPost(blogPostEdit.IdentityId);
// insert logic to push to BlogSpot here using the approach we described previously
}
2. You need to inherit the Blog.aspx and copy its markup. Remember to change the path in the Blog.aspx to point towards your custom BlogContainer.ascx control.
3. Change the web.config URL rewriting rules to point towards your custom Blog page.
Conclusion
This article demonstrated you how you can post, update or delete a blog post on the BlogSpot service. It also shows how to fetch a list of blog posts from BlogSpot and integrate it with your custom MonoX projects.
I am attaching a sample project which demonstrates the techniques described in this article.