Sitecore : Adding a Twitter Pod using LINQ To Twitter

In almost all the projects I have done in past year or so, a common requirement among the clients have been that they want the ability to add Twitter Pods on pages and also have the ability to change the account name based upon their campaign or department.

For the purpose of the post, I will be using Sitecore CMS and LINQ To Twitter library to show how simple it is to create a Twitter Pod/module.

Let suppose we only want to display top  tweet from an account/twitter handle, which is define in the Sitecore CMS

Steps:

1. Create a data template property in the CMS as ‘Twitter Account Name’ or whatever you like

2. Create a standard .NET User Control and lets call it ‘TwitterPod.ascx’

3. Reference LINQ to Twitter library in your project (download it from here http://linqtotwitter.codeplex.com/ and also read its documentation)

4. As per Twitter API 2.0 you need to get Consumer Key, Consumer Secret, Access Token, Access Token Secret values from http://dev.twitter.com for any applications that you are creating. Log-in there and follow the steps to get these values.

5. Add these Twitter API 2.0  values to web.config

6. Let suppose this is your .ascx control markup

<div><asp:HyperLink ID="HyperLinkFollowAccount" runat="server" Target="_blank"></asp:HyperLink></div>

<div class="twitter">
<asp:HyperLink ID="HyperLinkFirstTweet" runat="server">
<p><asp:Literal ID="LiteralFirstTweet" runat="server"></asp:Literal>
<p>Posted <asp:Literal ID="LiteralFirstPostedTime" runat="server"></asp:Literal></p>
</asp:HyperLink>
</div>

7. Add these ‘static strings’ to your User Control class

private static string ConsumerSecret

{

get { return WebConfigurationManager.AppSettings["ConsumerSecret"]; }

}

private static string ConsumerKey

{

get { return WebConfigurationManager.AppSettings["ConsumerKey"]; }

}

private static string AccessToken

{

get { return WebConfigurationManager.AppSettings["AccessToken"]; }

}

private static string AccessTokenSecret

{

get { return WebConfigurationManager.AppSettings["AccessTokenSecret"]; }

}

8.  Twitter API 2.0 requires OAuth Authentication, to get that add this to Page_Load of your User Control

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
var auth = new SingleUserAuthorizer
{
Credentials = new InMemoryCredentials
{
ConsumerKey = ConsumerKey,
ConsumerSecret = ConsumerSecret,
OAuthToken = AccessToken,
AccessToken = AccessTokenSecret
}
};

using (var twitterCtx = new TwitterContext(auth))
{
LoadTwitterFeeds(twitterCtx);
}
}
catch(Exception ex)
{
Sitecore.Diagnostics.Log.Error(ex.Message, this);
}
}
}

9.  LoadTwitterFeeds(twitterCtx) is your custom function where you can add your logic of getting tweets via Twitter API 2.0 and displaying them

10.

private void LoadTwitterFeeds(TwitterContext service)
{
try
{

string accountName = Sitecore.Context.Item["Twitter Account Name"] as string;

var tweets = (from tweet in service.Status

where tweet.ScreenName == accountName &&
tweet.Count == 1 &&
tweet.ExcludeReplies == true &&
tweet.IncludeRetweets == true &&
tweet.Type == StatusType.User
select tweet).FirstOrDefault();

if (tweets != null)
{

HyperLinkFollowAccount.NavigateUrl = "http://twitter.com/" + accountName.Replace("@", "");
HyperLinkFollowAccount.Text = "Follow " + accountName + " on Twitter";

LiteralFirstTweet.Text = tweets.Text;
LiteralFirstPostedTime.Text = tweets.CreatedAt.ToString();
HyperLinkFirstTweet.NavigateUrl = "https://twitter.com/" + tweets.User.Identifier.ScreenName + "/status/" + tweets.StatusID.ToString();}

catch (Exception ex)
{
Sitecore.Diagnostics.Log.Error(ex.Message, this);
}
}

11. Create a Sublayout for this User Control and add it to the Sitecore Layouts.

Note: You can also pass in the ‘Twitter Account Name’ as a parameter of the SubLayout
Note++: Umbraco and Episerver CMS can also use the same code with different CMS based API.

Thanks

Advertisements

EPiServer : Dynamic Data Store

If you are reading this post, then I can assume you are curios about EPiServer dynamic data store and want to know how to use it. In this post, I am going to do exactly the same. I will create, update and delete from DDS using EPiServer API.

1- Create a new dynamic data store

Imagine you have to dynamically store landing page ids for certain products or sections and then read them back from dynamic data store

private void CreateLandingPageDDS(PageData myPage)
{
//create a propertybag
PropertyBag landingProperties = new PropertyBag();

//add your custom properties
landingProperties.Add("LandingPageKey", myPage.PageLink.ID.ToString());
landingProperties.Add("LandingPageProductName", myPage.PageName);
//add more properties if you like, but there is a limit that you can add upto, or
//create a custom object and add that object

//create a new store for DDS
DynamicDataStore store = DynamicDataStoreFactory.Instance.CreateStore("DDS",   landingProperties.GenerateTypeBag());

//store DDS in database
Identity id = store.Save(landingProperties);

}

pretty simple 🙂

2- Get dynamic data store

Now let say you want to query the same DDS and would like to get pageName if you pass in the pageID

public static string GetLandingPageName(string currentPageID)
{
//get the store from database
DynamicDataStore store = (DynamicDataStore)DynamicDataStoreFactory.Instance.GetStore("DDS");

if (store != null)
{
//find all the properties for that key/value pair
IEnumerable<PropertyBag> landingProperties = store.FindAsPropertyBag("LandingPageKey", currentPageID);

//iterate through each property and return only where key matches
if (landingProperties != null)
{
foreach (PropertyBag item in landingProperties)
{
string pageName = item["LandingPageProductName"] as string ?? string.Empty;
return pageName;
}

}

}
return string.Empty;
}

Although pageName is a trivial property, this is just an example how to go about using DDS.

3- Update dynamic data store

Now let say you want to update pageName using pageID

private void UpdateLandingPage(string currentPageID)
{
DynamicDataStore store = (DynamicDataStore)DynamicDataStoreFactory.Instance.GetStore("DDS");

if (store != null)
{
IEnumerable<PropertyBag> landingProperties = store.FindAsPropertyBag("LandingPageKey", currentPageID);

if (landingProperties != null)
{
foreach (PropertyBag item in landingProperties)
{
item["LandingPageProductName"] = "New name";
store.Save(item);
}


}

}
}

4- Delete dynamic data store

That is very strait forward, just use

DynamicDataStoreFactory.Instance.DeleteStore("DDS",true);

5-Important note

If during development, you have to change your dynamic data store by adding more properties to property bag object, it will result in exception.

There are two ways to get round this

1.If you are in development, delete your previous DDS entries and start fresh
2.If you are in production, then you have to re-map/re-link the property bag.

Have fun coding DDS

EPiServer : CustomProperty for Radio Button List

EPiServer has lots of in-built properties, but one major property that it is missing is ‘radio button list’ , sometimes user wants to select just one option from give 4 or 5 options.

In this post, I will guide you through making a very basic custom property for EPiServer for ‘Radio Button List’

Step1: In your VS project, right-click and new EPiServer custom property control as show below, i will rename this control is ‘PropertyMyPicker’

Add custom property
Add custom property

Step2: Inherit it from ‘PropertyString’ as shown below

Inherit from property string
Inherit from property string

Step3: This will create two code files in your project as following

PropertyMyPicker.cs

PropertyMyPickerControl.cs

You do not need to do anything in ‘PropertyMyPicker.cs’ class, and all your logic will be implemented in  ‘PropertyMyPickerControl.cs’.

Step4: In this code snippet,  we create 3 radio buttons, if their value is selected, that text is stored in the database and when the page is re-visited/re-loaded the value is read back from the database. Change the code of the ‘PropertyMyPickerControl.cs’ as shown below and make necessary namespace and variable changes. You have overwrite some of the methods and implement your own if necessary.

/// <summary>
/// PropertyControl implementation used for rendering PropertyMyPicker data.
/// </summary>
public class PropertyMyPickerControl : EPiServer.Web.PropertyControls.PropertyStringControl
{
RadioButton radioButton1 = null;
RadioButton radioButton2 = null;
RadioButton radioButton3 = null;
// Value that will be stored in db,
string desc = string.Empty;
// group name for all radio buttons to make them behave as radiobuttonlist
readonly string groupName = "MyPicker";
/// <summary>
/// Gets the PropertyMyPicker instance for this IPropertyControl.
/// </summary>
/// <value>The property that is to be displayed or edited.</value>
public PropertyMyPicker PropertyMyPicker
{
get
{
return PropertyData as PropertyMyPicker;
}
}
/// <summary>
///creates radio button list and pre-select if the value
///has been saved in database
/// </summary>
public override void CreateEditControls()
{
//add radioButton1 radio button
radioButton1 = new RadioButton();
radioButton1.Text = "Radio 1 Text";
radioButton1.GroupName = groupName;
radioButton1.Checked = IsRadioChecked(radioButton1.Text);
//add radioButton2 radio button
radioButton2 = new RadioButton();
radioButton2.Text = "Radio 2 Text"
radioButton2.GroupName = groupName;
radioButton2.Checked = IsRadioChecked(radioButton2.Text);
//add radioButton3 radio button
radioButton3 = new RadioButton();
radioButton3.Text = "Radio 3 Text";
radioButton3.GroupName = groupName;
radioButton3.Checked = IsRadioChecked(radioButton3.Text);

this.Controls.Add(radioButton1);
this.Controls.Add(radioButton2);
this.Controls.Add(radioButton3);

}
/// <summary>
/// Saves it to the database
/// </summary>
public override void ApplyEditChanges()
{
desc = GetMyDescription();
base.SetValue(desc);
}
/// <summary>
/// Get selected radio button text
/// </summary>
/// <returns></returns>
private string GetMyDescription()
{
string selectedMyPicker = string.Empty;

if (radioButton1.Checked)
selectedMyPicker = "Radio 1 Text";
else if (radioButton2.Checked)
selectedMyPicker = "Radio 2 Text";
else if (radioButton3.Checked)
selectedMyPicker ="Radio 3 Text";

return selectedMy;

}
/// <summary>
/// Check if the controls contain value for any of the radio button in database
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private bool IsRadioChecked(string name)
{
if (this.PropertyData.Value != null)
{
string selectedMy = this.PropertyData.Value.ToString();
if (selectedMy.ToLower() == name.ToLower())
return true;
}
return false;
}

}

Step 5: Next you need to create the property for the page template, you will see your new property in the dropdown list

Step 6: You can use this property as a page string property and output your custom logic

//assuming MyPicker is the page property name
var myPicker = CurrentPage["MyPicker"] as string;

if (!String.IsNullOrEmpty(myPicker))
{
  //add your custom logic here
}

Thats it, job done!

Configuring video settings in EPiServer Relate+

I have recently worked on a project using standard out-of-box EPiServer Relate+ website and templates. As every module is very well written and integrated, the only missing piece was the video upload settings.

It took me a while to find out how to get these settings and update the site so that end user can upload video.  I thought it will be a good idea to write up a small blog for fellow developers.

Step 1. Navigate to http://world.episerver.com/System/Video-Service/ and login with your usual world.episerver account

Step 2. Select register account as shown below

register video

Step 3. The next screen will show your information, make sure all the required fields are there and click ‘Next’ (I have removed my auto generated email address)

video next

Step 4:  Read and Check the ‘Terms & Condition’ box. As I am using it for demo purposes, I would select the development license.

video confirm

Step 5: If your account is successfully created, you would be shown  <cdnProvider>  settings at the bottom of the page.

Step 6: Open your EPiServer Relate+ web.config and find the <cdnProvider> node and replace the accessKey and secretAccessKey values with the actual values generated at the end of the process.

Navigate to the actual site and try uploading any video. The video service modules converts all movies into flash format so it may take a while to upload your video and it will depend upon your system, network traffic and video file size.

Secondly, video files may not appear instantly on the page so just be patient.

Cheers

EpiChatty-EPiServer CMS gadget

Hi, here is my small contribution to the Gadget competition. Meet EpiChatty, your personal assistant (chat bot) that can give you help and information about EPiServer CMS. It could serve as a help desk assistant to EPiServer CMS editors / administrators / developers / designers and to content editors.

The main idea behind this is to have Google Talk client embedded as a gadget on dashboard and run EPiChatty as a console application which can interact with the user and give appropriate response.

Google Talk implements Extensible Messaging and Presence Protocol (XMPP) protocol which essentially exchange messages using XML between clients and servers. More information about this protocol can be found at http://xmpp.org/ and more information about Google Talk API can be found at http://code.google.com/apis/talk/

As Google do not provide any C# implementation of XMPP protocol and as I am primarily a C# developer,(not brave enough to try Google’s java based implementation for this protocol), so I have to look for different options. After bit more research,  I found out that agsXMPP is an open source SDK / library for the XMPP protocol which is written in managed C# and is dedicated to .NET and Mono technologies. More information can be found about this SDK can be found at .

With all my components in place, I have learn basics about the new protocol (which I have never used before) and also use the SDK to implement it (easy).  It took a while to do a ‘hello world’ kind of code, as Google server require a different port (5222) than 80 to be open as well so that it could communicate. Once I figured that out with help from support team at agsXMPP, next thing was to implement the automated behaviour for the asked questions.

There are several ways that this could be implemented, but I went for the XML based approach. I have stored questions and answers in a set patterned way so that if user ask ‘what is’ or ‘how to’ or any ‘generic’ question, a patterned would be matched and answer would be returned. The main reason behind this approach was its simplicity and extendibility.

Here is the screen shot how the EPiChatty gadget will look like on dashboard

The gadget view contains embedded Google Talk client and the controller simply returns the view.  The login it will redirect to central Google account services where you could login and then it will return you back to the dashboard.

once login you can ask ‘what is’ or ‘how to’ or ‘generic’ questions



Here is the screen shot of the console application showing that EPiChatty is available to chat


I have made the EPiChatty as a console application so that it could run separately from the main application as a light weight process in background. In case you want to start chatting and test it out, send an invite to epichatty@googlemail.com . I will be hosting it till the end of December 2009 and then EPiChatty will be on long vacations.

Source files contain every thing apart from the password for the EPiChatty Google’s account. If you would like to host your own, you can create a new Google account and replace the username and password in console application and run the console application.

Source