More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  MSN and Windows LivePhotosProfileFriendsMore Tools Explore the Spaces community
Updated 11/9/2007
Updated 7/11/2008
Updated 10/10/2006

MSN and Windows Live

Tips, tricks and information regarding MSN and Windows Live. See also http://hackersoftmvp.spaces.live.com/
August 01

The Ultimate HTML Reference - Review

Title : The Ultimate HTML Reference
Author : Ian Lloyd
ISBN : 0980285887
Price : $44.95
Rating : 4 out of 5

As I’m currently off work due to surgery I thought there’s no better time to read some of the books that I haven’t gotten around to read yet. As such here is the first of my reviews for this week.

In previous years I was never very enchanted with Sitepoint titles however over the past year or so Sitepoint seem to have upped their game and have published a number of fairly good titles. This book being one of them.

The ultimate HTML reference by Ian Lloyd is exactly what it says, a reference guide. Although I’ve read the book cover to cover it is meant more as a reference book than a straight read. The book covers every single HTML/XHTML tag and corresponding attribute known (including some that aren’t even in the official ratified HTML standard but are supported by certain browsers, mainly during the browser wars from a few years ago) from HTML version 1 right through to HTML 4.01 and also includes XHTML through version 1.1.  Unfortunately you won’t find any HTML 5 or XHTML 2.0 tags or extensions in the book but that is mainly because these haven’t been ratified by the W3C yet.

The book is very well laid out with each each attribute to a tag immediately following the tag and a quick reference stating exactly what tag the attribute is associated with (which is handy for a reference guide). Next to this is a quick reference stating whether or not the tag or attribute has been deprecated, whether it’s required, the version of HTML or XHTML that it was introduced and a quick browser support reference stating whether it’s fully supported by the browser, partially supported, not supported at all or whether the implementation is buggy for a particular browser.  This is followed by a description of what the tag or attribute does, any values that it takes followed by a more complete browser compatibility list. The list covers the major browsers that are currently out from IE5.5 through IE7, Firefox 1.0 through 2.0, Safari 1.3 through 3.0 and Opera 9.2. This is followed by a brief description of any compatibility issues as listed finally followed by a list of other relevant tags or attributes.  As with any book of this nature, basically it is out of date virtually as it’s printed. With Firefox 3.0 and Opera 9.5 just being released and Internet Explorer 8.0 just around the corner, however there are mentions of these scattered throughout the book e.g. the “X-UA-Compatible” attribute of the http-equiv that was introduced with IE8. Unfortunately since the book went to print Microsoft have changed their mind and this tag is no longer necessary to put IE8 into full compatibility mode as it will ship in that mode as default.

There are also numerous references to web articles like RFC’s that the reader can use for further information should they be inclined. Also there are tips as to what CSS styling you should use instead if an attribute be deprecated.

This leads me to one of my biggest complaints about this good. Reading through it you just get the feeling that as well as the HTML/XHTML reference, there should also be a CSS reference. It just seems so natural a fit to this type of book, however as the title suggests this book only covers HTML/XHTML. As such Ian Lloyd has done an insanely outstanding job of providing all the information you could ever want about any HTML element or attribute. This is definitely a book that will be sitting on my desk and one that I will dip into every now and again and one that you should have too.  I just hope that there is a companion book in the works detailing CSS in the same manner.

July 11

Cheap and Easy Online Helpdesk

A lot of professional sites are now including a means of real time chat as part of their helpdesk sites. MSDN has their online concierge service, Dell has an online help, AT&T etc.  So how do you do this type of thing within your own web site?
Well thanks to the Windows Live Web Messenger API it's actually quite easy to do. 

In previous articles I've covered how to incorporate Windows Live Messenger into your own site. This article simply takes that process one step further by allowing you to host your own online Helpdesk chat system. 

The code in this article is actually very similar to the code in the previous articles I've posted and so I won't be going over all the functions again, instead I will point out the differences between this application and the previous one.

 

SolutionExplorer

As you can see, the site structure is exactly the same. The Privacy.htm and Channel.htm required files are present.  There are a few graphics files, a theme and everything else is contained in the Default.aspx file.

The main body of the html code found in Default.aspx is the same as in my previous articles however we've removed a couple of features as these aren't strictly necessary for a helpdesk application :-

 

<body onload="scriptMain()">
    <form id="form1" runat="server">
   <div id="msgr">
   <table>
   <tr><td>
   <div id="signinframe"></div>
   </td></tr>
   <tr><td>
   <div id="userInfo"></div>
   </td></tr>
   <tr><td>
   <div id="sendMessage">
    <hr />
    <span><b>Send a Message:</b></span>
    <p id="contactLabel"></p>
    <p id="msgLastRecv"></p>
    <div id="txtConv"></div><br />
    <input id="txtMessage" type="text"/><br />
    <input onclick="sendMsg()" id="btnSend" type="button" value="Send Message" disabled="disabled" />
   </div>
   </td></tr>
   <tr><td>
   <div id="divConversations"></div>
   </td></tr>
   <tr><td>
        <div id="Contacts">
            <p><b>Helpdesk Contact
                <a href="Javascript:ToggleContacts();">
                <img alt="ToggleContacts" src="minus_icon.gif" id="ContactsExpand" class="ContactImage" />
                </a>
            </b></p>
               <div id="divContacts"></div>
        </div>
   </td></tr> 
   </table>
   </div>
    </form>
</body>
 

As you will notice there no longer is a placeholder  to change your online status and I've also removed the placeholder that allowed you to change your personal message. The rest however is the same.

Once rendered it should look like this :-

HelpDeskApp

The basis of this program is that you go to a specific page on a site if you are having a problem and chat to someone from the site to help solve your problem. You want this to all be automatic and for your user to do as little as possible to enable this. With the upcoming launch of Windows Live Messenger 9, this actually becomes scalable to a point as Messenger 9 allows for multiple presences on the same Live ID. Therefore you could have multiple team members, all sign into the same Live ID and all handling chats at the same time.
To make this as transparent as possible to the end user, once the user logs in with their Windows Live ID, you should check to see whether or not your pre-defined Help Desk Live ID is currently present in the users contact list, if it is great, pre-select that ID and the user can start chatting with you. If not then you will need to add your Help Desk Live ID transparently and select it so that the user can start a conversation with you. All of this is actually quite easy to accomplish.

The user comes along to your site where you have your Live Web Messenger application and is prompted to sign-in.

WLSignin

This is the same process and code as in the previous article so I won't regurgitate it here. Basically they are taken away from your site to the Windows Live login site, they enter their credentials and are then taken back to your site. The sign-in screen actually gets presented to them as a pop-up window so as not to completely take them away from your site.

SigningIn

You application changes to reflect the fact that the user is signing in. At this point the application is awaiting the token back from the Windows Live Login site saying that the user is authenticated.

Once signed in the user is able to chat to the help desk representative :-

SignedIn

As you will notice from the above screen shot, we don't display all of the users contacts, we only display the help desk contact. Why do we even want to display this? Well it's helpful to see whether someone is actually signed on and manning the online help desk or not, as is reflected in the status displayed next to the contact (in the above example the person is not currently online).

So what changes in the code do we need from my previous articles to get this to work?  Basically it all happens in the displayContacts() routine :-

 

function displayContacts() 
    {
   var sb = new StringBuilder();
   var HelpDeskIndex = null;
   _addressList = new Array(_user.get_contacts().get_count());
    var groupList = new Array(_user.get_groups().get_count());
   var enum2 = _user.get_groups().getEnumerator();
   var enum1 = _user.get_contacts().getEnumerator();
   var groupindex = 0;
        index = 0;
   while (enum2.moveNext())
   {
        var c = enum2.get_current();
    var _contacts = new Array(c.get_contacts().get_count());
        var enum3 = c.get_contacts().getEnumerator();
        while (enum3.moveNext()) 
        {
    var contact = enum3.get_current();
    var address = contact.get_currentAddress();
    var dispName = address.get_presence().get_displayName();
    var currAddress = address.get_address();
    var status = Enum.toString(Microsoft.Live.Messenger.PresenceStatus, address.get_presence().get_status());
        //Check to see if Helpdesk account is present
        if(currAddress.toLowerCase() == "Your helpdesk address")
        {
            HelpDeskAdded = true;
        var statusimg = null;
        switch(status)
            {
                case "online":
                    statusimg = "<img src='online.gif' class='ContactImage' alt='online' />";
                    break;
                case "offline":
                    statusimg = "<img src='offline.gif' class='ContactImage' alt='offline' />";
                    break;
                case "appearOffline":
                    statusimg = "<img src='offline.gif' class='ContactImage' alt='offline' />";
                    break;
                case "away":
                    statusimg = "<img src='away.gif' class='ContactImage' alt='away' />";
                    break;
                case "beRightBack":
                    statusimg = "<img src='away.gif' class='ContactImage' alt='beRightBack' />";
                    break;
                case "busy":
                    statusimg = "<img src='busy.gif' class='ContactImage' alt='busy' />";
                    break;
                case "idle":
                    statusimg = "<img src='away.gif' class='ContactImage' alt='idle' />";
                    break;
                case "inACall":
                    statusimg = "<img src='busy.gif' class='ContactImage' alt='InACall' />";
                    break;
                case "outToLunch":
                    statusimg = "<img src='away.gif' class='ContactImage' alt='OutToLunch' />";
                    break;
                default:
                    statusimg = "<img src='offline.gif' class='ContactImage' alt='offline' />";
                    break;
            }
    var statusLine = '';
    var strDelete = '';
    _addressList[index] = address;
    if (dispName !== '') 
    {
            statusLine = '<a href=\'javascript:createConv(' + index + ')\'>' + statusimg + dispName + '</a>';
        }
        else 
        {
            statusLine = '<a href=\'javascript:createConv(' + index + ')\'>' + statusimg + currAddress + '</a>';
        }
    sb.append(statusLine);
        HelpDeskIndex = index;
        }
    index++;
    }
        groupindex++;
        index = 0;
        while (enum1.moveNext()) 
        {
    var contact = enum1.get_current();
    var address = contact.get_currentAddress();
    var dispName = address.get_presence().get_displayName();
    var currAddress = address.get_address();
    var status = Enum.toString(Microsoft.Live.Messenger.PresenceStatus, address.get_presence().get_status());
 
        if(currAddress.toLowerCase() == "Your helpdesk address")
        {
            HelpDeskAdded = true;
 
        //Change status to an image
        var statusimg = null;
        switch(status)
        {
            case "online":
                statusimg = "<img src='online.gif' class='ContactImage' alt='online' />";
                break;
            case "offline":
                statusimg = "<img src='offline.gif' class='ContactImage' alt='offline' />";
                break;
            case "appearOffline":
                statusimg = "<img src='offline.gif' class='ContactImage' alt='offline' />";
                break;
            case "away":
                statusimg = "<img src='away.gif' class='ContactImage' alt='away' />";
                break;
            case "beRightBack":
                statusimg = "<img src='away.gif' class='ContactImage' alt='beRightBack' />";
                break;
            case "busy":
                statusimg = "<img src='busy.gif' class='ContactImage' alt='busy' />";
                break;
            case "idle":
                statusimg = "<img src='away.gif' class='ContactImage' alt='idle' />";
                break;
            case "inACall":
                statusimg = "<img src='busy.gif' class='ContactImage' alt='InACall' />";
                break;
            case "outToLunch":
                statusimg = "<img src='away.gif' class='ContactImage' alt='OutToLunch' />";
                break;
            default:
                statusimg = "<img src='offline.gif' class='ContactImage' alt='offline' />";
                break;
            }
    var statusLine = '';
    var strDelete = '';
    _addressList[index] = address;
    if (dispName !== '') 
    {
            statusLine = '<a href=\'javascript:createConv(' + index + ')\'>' + statusimg + dispName + '</a>';
        }
        else 
        {
            statusLine = '<a href=\'javascript:createConv(' + index + ')\'>' + statusimg + currAddress + '</a>';
        }
    sb.append(statusLine);
        HelpDeskIndex = index;
        }
    index++;
    }
        groupindex++;
        }
   document.getElementById('divContacts').innerHTML = sb.toString();
   if(HelpDeskAdded == true)
   {
       createConv(HelpDeskIndex);
   }
    else
    {
        alert(HelpDeskAdded);
        var helpDeskContact = "Your helpdesk address";
        if(_user !== null)
        {
        alert(_user);
            _user.addContact(helpDeskContact, "Please accept in order to converse with the helpdesk", null);
            HelpDeskAdded = true;
        }
    }
    }

Overall this routine is very similar to the displayContacts() routine explained thoroughly in my previous articles however there are a few changes and also a hack (workaround) to a problem I came across, which I'll get to in a minute.
So first we get a list of all the contacts that the user has in their contacts list. Then we loop through each of these contacts to determine whether your helpdesk Live ID is present :-

if(currAddress.toLowerCase() == "your helpdesk address")

Simply replace "your helpdesk address" with your help desks live id. Make sure however that it is all in lower case as you'll see from the line of code that that's how the code does the comparison.

If the contact is found then we get the contacts status and create a string to display their information in the contacts section at the bottom of the application.

Now you'll notice from the code that this basic routine looks like it's present twice. This is actually the quick hack. The reason for this is the way Live Contacts can be stored. Most contacts are actually assigned to a group and you may have multiple groups with multiple contacts in each. However some contacts are actually stored outside of groups and are in effect free floating.  This hack gets around that problem. The first routine searches through all the contacts that belong to groups, the second section (which is essentially the same code) searches through the contacts that aren't assigned to any group.

if(HelpDeskAdded == true)
{
    createConv(HelpDeskIndex);
}
  else
  {
 
      var helpDeskContact = "Hackersoft@live.com";
      if(_user !== null)
      {
 
        _user.addContact(helpDeskContact, "Please accept in order to converse with the helpdesk", null);
        HelpDeskAdded = true;
      }
  }

At the bottom we have the check to see whether the help desk contact has been added or not. If it's already present then we are ready to start a conversation, if not then we need to add the help desk contact to the users contact list. The HelpDeskAdded variable is a global variable defined later in the code. And that's basically it.

One last point, I came across a bug in my previous articles. Before I had the :-

index = 0;

placed within the loop, this actually caused problems when trying to chat with the correct contact. This has now been moved outside of the loop.

For the complete source file see this post (due to limitations in Live Spaces)

Conversation

With this you now have a fully functional interactive help desk chat application that you can add to your site.

June 18

Review - Advanced Asp.Net Ajax Server Controls for .Net Framework 3.5

Title : Advanced ASP.NET AJAX Server Controls For .NET Framework 3.5
Author : Adam Calderon
  Joel Rumerman
ISBN : 0321514440
Price : $49.99
Rating : 4.5 out of 5


I got given an advanced "Draft Manuscript" copy of this book from Pearson (the publishers) whilst at Tech-Ed which is why I can write this review before the book is officially published.
First off, let me say that I love this series of "Microsoft.Net Development Series" by Addison Wesley. For information regarding virtually anything .Net, this is really the first series of books that you should take a look at. Most of the books are written by the product teams themselves however this title is not (although the authors have had a great deal of feedback and input from the product teams involved).
This book isn't really about learning Asp.Net Ajax. It takes a more specific topic that little has been written about and the authors have done an excellent job in covering it from end to end. That niche, is developing server controls that integrate Asp.Net Ajax, giving them more functionality and updating web controls to the "Web 2.0" style controls a lot of companies are developing at the moment.
The book starts off with a quick overview of some of the more esoteric aspects of Javascript although it doesn't actually teach you Javascript, it is assumed that you already know this, it gives you a good overview of the basics on how the Microsoft Asp.Net Ajax framework has been written and sets you up to better understand it and extend it for your own needs.
Following this is a chapter on the new "Types" that the Asp.Net Ajax framework introduces as first class components and also how to extend the framework, adding your own classes, interfaces etc. to it.
Without going chapter by chapter, the book covers everything you actually need to know, and a lot more, on how to integrate Ajax into your own Asp.Net server controls. It covers the differences between the Asp.Net Ajax framework 1.0 and that which was released and integrated into the .Net Framework 3.5 where applicable (the book is intended for the .Net Framework 3.5 and Visual Studio 2008).
There are plenty of code examples throughout the book, building on what was covered in previous chapters you gain a thorough understanding of exactly what this book sets out to do.
The writing style isn't as stolid as most other technical books and is actually easy to read and flowing.
There are a few typos and mis-spellings in the copy that I have but I'm sure that these will be resolved for the final published version.
If you develop Asp.Net web server controls then this is a book you must have. Even if you don't program server controls but just do standard Asp.Net pages, this book gives you a lot of information about how to use Asp.Net Ajax in your projects. Overall a highly recommended book.

May 21

How to use Teleriks' RadChart control within Sharepoint

I have been playing around with the Telerik controls over the past couple of months and decided to see if I could incorporate their RadChart control into Sharepoint.

RadChartLogo

The basis was to create a custom web part that houses the RadChart control. That web part then points to a list and gets its data from the list and creates the chart. It's a fairly easy process but there are a couple of gotchas to watch out for. So let's get started.

The first thing you need to do is to download the "Dev" zip file from Telerik so that you can do a manual deployment, rather than the normal automated MSI file.  Once you have that, unzip it. There are two things you need to deploy from this.  Open up Windows Explorer on your Sharepoint box and browse to your Sharepoint Site directory (usually found under c:\inetpub\wwwroot\wss\VirtualDirectories somewhere). Then open up the bin directory as this is where you will copy the Web Chart dll.
Next open another instance of internet explorer and browse to where you unzipped the Telerik controls. In here go to the NET2 folder then the bin directory in there. Locate RadChart.Net2.dll and drag it into your other windows explorer window (which should place a copy of it in your Sharepoint sites bin directory).

Next you need to register the RadChart so that it's marked as safe in the web.config file. Open the web.config file for your Sharepoint site and add the following to the end of the SafeControls list :-

<SafeControl Assembly="RadChart.Net2, Version=4.1.1.0, Culture=neutral, PublicKeyToken=d14f3dcc8e3e8763" Namespace="Telerik.WebControls" TypeName="*" Safe="True" />

This is the RadChart 2007 Q3 SP1 version. If you've got a different version of the RadChart then these values will be slightly different, namely the version number and the PublicKeyToken.

Now Sharepoint can theoretically display charts, but without some custom coding it obviously won't be able to.

RadCharts 

Next open your copy of Visual Studio and create a class file (I actually used Visual Studio 2005 SP1 for this and download the Sharepoint Extensions for Visual Studio 2005 and used the Sharepoint Web Part project to build this with. Makes things slightly easier).

Once you have your project open in Visual Studio, you need to include a reference to the RadChart dll (In solution explorer, right click and select Add Reference then browse to where the dll resides).

Now to the code :-

using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Telerik.WebControls;
using Telerik.Charting;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Security;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Collections.Generic;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

[assembly:AllowPartiallyTrustedCallers]

This first part are the includes that you will need along with the AllowPartiallyTrustedCallers attribute which is required for Sharepoint.

namespace WebChart
{
    [Guid("2bee1192-339c-4f85-849d-2df6f24c24d4")]
    public class WebChartPart : System.Web.UI.WebControls.WebParts.WebPart
    {
        #region Private Properties
        private string m_Web = string.Empty;
        private string m_Site = string.Empty;
        private string m_List = string.Empty;
        private string m_ChartData = string.Empty;
        private string m_ChartText = "Title";
        #endregion

Next we define our class and namespace and also create some local variables. These variables will be used by public properties that will show up Sharepoint to allow users to set which list, columns etc. to get the data from.

        #region Editor Properties
        [WebBrowsable(true),
        Category("Chart Settings"),
        /* DefaultValue(m_Web), */
        Personalizable(PersonalizationScope.Shared),
        DisplayName("MOSS Site"),
        WebDisplayName("MOSS Site"),
        WebDescription("The Top Level MOSS Site where the list resides.")]
        public string Web
        {
            get 
            {
                return m_Web; 
            }
            set 
            { 
                m_Web = value; 
            }
        }

        [WebBrowsable(true),
        Category("Chart Settings"),
        /* DefaultValue(m_Site), */
        Personalizable(PersonalizationScope.Shared),
        DisplayName("Sub Site"),
        WebDisplayName("Sub Site"),
        WebDescription("The actual MOSS Site where the list resides.")]
        public string MOSSSite
        {
            get
            {
                return m_Site;
            }
            set
            {
                m_Site = value;
            }
        }

        [WebBrowsable(true),
         Category("Chart Settings"),
        Personalizable(PersonalizationScope.Shared),
        DisplayName("Sub Site"),
        WebDisplayName("List Name"),
        WebDescription("The list where the chart data resides.")]
        public string MOSSList
        {
            get
            {
                return m_List;
            }
            set
            {
                m_List = value;
            }
        }

        [WebBrowsable(true),
         Category("Chart Settings"),
         /*   DefaultValue(m_Site), */
        Personalizable(PersonalizationScope.Shared),
        DisplayName("Sub Site"),
        WebDisplayName("Chart Data"),
        WebDescription("The numeric column within the list to get the data.")]
        public string ChartData
        {
            get
            {
                return m_ChartData;
            }
            set
            {
                m_ChartData = value;
            }
        }

        [WebBrowsable(true)]
        [Category("Chart Settings")]
        /* [DefaultValue(m_Site)] */
        [Personalizable(PersonalizationScope.Shared)]
        [DisplayName("Sub Site")]
        [WebDisplayName("Chart Text")]
        [WebDescription("The text column within the list to get the chart text.")]
        public string ChartText
        {
            get
            {
                return m_ChartText;
            }
            set
            {
                m_ChartText = value;
            }
        }

        #endregion

And here are the public properties. One for each of the private variables we declared earlier. These all follow the same procedure. First you decorate the property with attributes that tell Sharepoint which grouping to list them under in the Edit Properties pane, what you wish to call this property, how to store the values within Sharepoint etc. Then we just have a standard getter/setter pair pointing back to our private variables.
At the end of the day, this is what will appear in the Edit Properties window :-

Settings

Next we need to instantiate our RadChart control :-

        #region Controls
        Telerik.WebControls.RadChart chart = new RadChart();
        #endregion

We don't need to do anything with the class constructor. However we do need to override the CreateChildControls method. This is where we will be adding the RadChart to the web parts controls for display :-

       public WebChartPart()
        {
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            if (m_List != string.Empty)
            {
                GetSites();
                //GetFolders();
                chart.UseSession = false;
                chart.RadControlsDir = "~/_wpresources/RadControls";
                chart.TempImagesFolder = "~/_wpresources/RadControls/Chart/TempImages";
                BuildChart();
                this.Controls.Add(chart);
            }
        }

First we make sure any other controls and created, then check to see if the List public property actually has a value. If not then there obviously won't be any data for the chart so we simply don't display the chart. If it does have a value then we get all the data to build the chart and then display the control.  There are a couple of things worthy of mention here :-

  1. You must set UseSession to false otherwise you will run into problems with security.
  2. If you are going to be using this web part across multiple sites then the best place to put the RadControls directory is under the wpresources directory. Not the local one found within your sites hierarchy but the main one found at c:\program files\common files\microsoft shared\web server extensions\
  3. You also need to create a Temp directory. This is where the RadChart will temporarily store the actual chart images. Again the best place to put this is in the global wpresources directory as described above.

As noted above there is something else that you need to copy over from your RadControls zip file. Go to where you unzipped all the controls then go to the Net2\RadControls directory. Within there you will find a Chart folder.  Copy this folder.  Next to go c:\program files\common files\microsoft shared\web server extensions\wpresources and create a folder in there called RadControls. Paste the Chart directory you just copied into the RadControls folder.
Now within the Chart folder create another folder and call it "TempImages".  Your folder hierarchy should look like this :-

DirStructure

Back to Visual Studio and our next method :-

        private void GetSites()
        {
            if (m_Web == string.Empty)
            {
                SPWeb myweb = SPControl.GetContextWeb(this.Context);
                m_Web = myweb.Url;
            }
        }

All that this method does is pre-populate the web site public property with the url of the current site where the web part is deployed.

        private void BuildChart()
        {
            ArrayList numbers = new ArrayList();
            ArrayList text = new ArrayList();
            SPWeb myweb = SPControl.GetContextWeb(this.Context);
            SPList list = myweb.Lists[m_List];
            for (int i = 0; i < list.ItemCount; i++)
            {
                SPListItem item = list.Items[i];
                numbers.Add(Convert.ToInt32(item[m_ChartData].ToString()));
                text.Add(item[m_ChartText].ToString());
            }
            chart.ChartTitle.TextBlock.Text = list.Title;
            ChartSeries series = new ChartSeries();
            series.Name = list.Title;
            series.Type = ChartSeriesType.Pie;
            for (int i = 0; i < numbers.Count; i++)
            {
                int j = Convert.ToInt32(numbers[i]);
                series.AddItem(j, Convert.ToString(text[i]));
            }
            chart.Series.Add(series);
        }
    }
}

Finally we have our BuildChart method. We first create two lists, one to hold the text to be displayed and one to hold the numerical data that will make up the chart. Next we fill these two arrays from the list pointed to by the values entered in the Edit Web Part Properties window that the user will enter.
We then create a new ChartSeries object, give it a name, set it to display a pie chart and then insert our data into this ChartSeries object through the AddItem method.
Finally we add this ChartSeries to our chart and that's it. 

Compile your dll, put it in your Sharepoint sites bin folder and add it to the safecontrols. if you use the code below then your safecontrol entry should look similar to :-

<SafeControl Assembly="WebChart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5" Namespace="WebChart" TypeName="*" Safe="True" />

Add your web part to the page, edit the web part properties to point to a valid site, list and data and there you have it. The sample list I used I only put two values in for testing and here are the results :-

WebChartPart

You now have a fully functional RadChart control that can be embedded in your Sharepoint sites.  Here is the full code for the above :-

using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Telerik.WebControls;
using Telerik.Charting;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Security;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Collections.Generic;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

[assembly:AllowPartiallyTrustedCallers]

namespace WebChart
{
    [Guid("2bee1192-339c-4f85-849d-2df6f24c24d4")]
    public class WebChartPart : System.Web.UI.WebControls.WebParts.WebPart
    {
        #region Private Properties
        private string m_Web = string.Empty;
        private string m_Site = string.Empty;
        private string m_List = string.Empty;
        private string m_ChartData = string.Empty;