Blog

Blogging on programming and life in general.

  • A little while back I renamed all URL’s within my SharePoint 2007 virtual environment. You can view my posting here. When it came to viewing users My Site, the new URL did not update after making changes to the Alternate Access Mappings within Central Administration.

    So if you have the same problem or if you just need to change your My Site URL, here is a tutorial on how to fix this problem:

    1. Go to “Alternate Access Mappings” in SharePoint Central Administration > Operations. Click on the URL that corresponds to your My Site. This will take to you to the “Edit Internal URLs” page, allowing you to modify the My Site URL.

    Alternate AccessMappings

    Edit Internal Urls

    1. Go to “My Site Settings” which can be found in the Shared Service you configured in Shared Services Administration. Again, enter your new My Site URL.

    My Site Settings

    1. Modify your IIS site host header value to match the URL your entered in Central Administration.

    2. Carry out an iisreset.

  • I created a SharePoint 2007 installation on a Development Virtual Server. The installation and configuration of SharePoint was no problem. It actually went quite smoothly compared to my previous attempts. Lucky me! I thought to myself: “Man, things can’t get better than this”.

    But I then encountered a small hitch. For some reason, I could not view my intranet through Internet Explorer. The login popup box kept of appearing even though my user credentials were correct. I had no problem accessing my Intranet in Firefox. As much as I love to use Firefox (because it is such an awesome browser), some SharePoint features are restricted when a non-IE browser is used.

    The first thing I did was to add my SharePoint intranet URL to my Local Intranet trusted sites in Internet Explorer settings. From looking on the Internet, this has worked for some SharePoint developers. However, this did not fix my problem.

    Add to trusted sites

    This confirmed that Internet Explorer is not passing my login credentials to Active Directory causing problems when it came to authentication. I started snooping around Internet Information Services and viewed the Authentication Settings: Directory Security tab > Authentication and Access Control > Edit.

    I changed my authentication in IIS for all my intranet web sites: Central Administration, Main Portal and My Site. By default, the IIS Authentication methods were set to Enable Anonymous Access and Integrated Windows Authentication. I removed these options and just selected: Basic Authentication.

    Authentication Methods

    After you have changed these settings just carry out an iisreset.

  • I have noticed that one of many reasons clients like to get on to the SharePoint bandwagon is to use its detailed Document Management features to control the life cycle of each individual document within their organisation.

    This got me thinking. Most organisations have hundreds, if not thousands of documents they would like to move from their networked storage devices to the SharePoint 2007 platform. It would be time consuming to upload all these documents to a document library. So I decided to create a C# application that would allow me to upload multiple files from a folder on a PC to a document library web part of my choice.

    Just to note, this program I created has not been tested to upload documents in their thousands. I have tested uploading over 100 documents successfully. But feel free to modify my code to work more efficiently! ;-)

    SharePoint Document Uploader

    As you can see from my program above, I have managed to upload numerous documents from “Z:\My Received Files” to a document library called “Shared Documents”.

    SharePoint Document Library

    I created my program by using the following code:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using Microsoft.SharePoint;
    using System.IO; 
     
    namespace MOSSDocumentLibraryUploader
    {
        public partial class frmHome : Form
        {
            public frmHome()
            {
                InitializeComponent();
            }
      
            private void frmHome_Load(object sender, EventArgs e)
            {
                ddlDocumentLibList.Enabled = false;
                ddlSubSites.Enabled = false;
            }
     
            private void btnStartUpload_Click(object sender, EventArgs e)
            {
                lstUploadedDocuments.Items.Add(String.Format("Upload operation started at {0} {1}", DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString()));
     
                //Start uploading files
                try
                {
                    //Get site collection, website and document library informationn
                    SPSite intranetSite = new SPSite(txtIntranetUrl.Text);
                    SPWeb intranetWeb = intranetSite.AllWebs[ddlSubSites.SelectedItem.ToString()];
                    SPList documentLibrary = intranetWeb.Lists[ddlDocumentLibList.SelectedItem.ToString()];
     
                    intranetWeb.AllowUnsafeUpdates = true;
                    intranetWeb.Lists.IncludeRootFolder = true;
     
                    //Start iterating through all files in you local directory
                    string[] fileEntries = Directory.GetFiles(txtDocumentDirectory.Text);
     
                    foreach (string filePath in fileEntries)
                    {
                        SPFile file;
     
                        //Get file information
                        FileInfo fInfo = new FileInfo(filePath);
     
                        Stream fileStream = new FileStream(filePath, FileMode.Open);
     
                        //Load contents into a byte array
                        Byte[] contents = new Byte[fInfo.Length];
     
                        fileStream.Read(contents, 0, (int)fInfo.Length);
                        fileStream.Close();
     
                        //Upload file to SharePoint Document library
                        file = intranetWeb.Files.Add(String.Format("{0}/{1}/{2}", intranetWeb.Url, documentLibrary.Title, fInfo.Name), contents);
                        file.Update();
     
                        lstUploadedDocuments.Items.Add(String.Format("Successfully uploaded: {0}", fInfo.Name));
     
                        lstUploadedDocuments.Refresh();
                    }
     
                    //Perform clean up
                    intranetWeb.Dispose();
                    intranetSite.Dispose();
     
                    lstUploadedDocuments.Items.Add(String.Format("Operation completed at {0}", DateTime.Now.ToLongTimeString()));
                }
                catch (Exception ex)
                {
                    lstUploadedDocuments.Items.Add(String.Format("Error: {0}", ex));
                }
            }
     
            private void btnCancelUpload_Click(object sender, EventArgs e)
            {
                lstUploadedDocuments.Items.Add(String.Format("Upload operation cancelled at {0} {1}", DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString()));
            }
     
            private void txtDocumentDirectory_Validating(object sender, CancelEventArgs e)
            {
                if (((TextBox)sender).Text == "")
                {
                    MessageBox.Show("You must enter an upload directory.", "Invalid Input", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
                else if (!Directory.Exists(((TextBox)sender).Text))
                {
                    MessageBox.Show("Document upload directory does not exist.", "Directory Does Not Exist", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
     
            private void txtIntranetUrl_Validating(object sender, CancelEventArgs e)
            {
                if (((TextBox)sender).Text == "")
                {
                    MessageBox.Show("You must enter a intranet url.", "Invalid Input", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
     
            private void btnExit_Click(object sender, EventArgs e)
            {
                this.Close();
            }
     
            private void ddlSubSites_SelectedIndexChanged(object sender, EventArgs e)
            {
                try
                {
                    ddlDocumentLibList.Enabled = true;
     
                    //Get site collection, website and document library informationn
                    SPSite intranetSite = new SPSite(txtIntranetUrl.Text);
                    SPWeb intranetWeb = intranetSite.AllWebs[ddlSubSites.SelectedItem.ToString()];
     
                    intranetWeb.Lists.IncludeRootFolder = true;
     
                    //Iterate through all document libraries and populate ddlDocumentLibList
                    foreach (SPList docList in intranetWeb.Lists)
                    {
                        ddlDocumentLibList.Items.Add(docList.Title);
                    }
                }
                catch
                {
                    ddlDocumentLibList.Enabled = false;
                }
            }
     
            private void txtIntranetUrl_TextChanged(object sender, EventArgs e)
            {
                try
                {
                    ddlSubSites.Enabled = true;
                    ddlDocumentLibList.Enabled = true;
     
                    //Get site collection, website and document library information
                    SPSite intranetSite = new SPSite(txtIntranetUrl.Text);
     
                    //Iterate through all sites and propulate ddlSubSites
                    foreach (SPWeb web in intranetSite.AllWebs)
                    {
                        ddlSubSites.Items.Add(web.Url.Replace(txtIntranetUrl.Text, ""));
     
                        //Iterate through child sites
                        foreach (SPWeb childSite in web.Webs)
                        {
                            ddlSubSites.Items.Add(childSite.Url.Replace(txtIntranetUrl.Text, ""));
                        }
                    }
                }
                catch
                {
                    ddlSubSites.Enabled = false;
                    ddlDocumentLibList.Enabled = false;
                }
            }
        }
    }
    

    It would have been really cool if my program only listed Document Libraries instead of all lists within a portal site. Unfortunately, I could not find any code to get a list of type Document Library. If anyone knows how to do this, I would be grateful if you could post some code.

    If you have any questions on the code or know of a better (free) solution out there, please leave a comment.

  • Debugging a page that uses many methods from other classes can become a right pain in the neck. I find myself accidentally stepping into a method that I don’t need to debug or wanting to output specific values from my methods straight away. Being the cowboy (correction, agile) developer that I am, one of my code boffins at work showed me a two cool ways to meet my debugging needs:

    1) DubuggerHidden Attribute

    Using the DubuggerHidden attribute tells the Visual Studio debugger that the method is hidden from the debugging process. The simple example below, shows the DebuggerHidden attribute in use:

    protected void btnDoSomething_Click(object sender, EventArgs e)
    {    
        //Output random number to Textbox
        txtOutput.Text = GetNumber(1, 10).ToString();
    } 
     
    [DebuggerHidden]
    int GetNumber(int min, int max)
    {    
        System.Random random = new Random();
        return random.Next(min, max);
    }
    

    2) DebuggerDisplay Attrubute

    The DebuggerDisplay attribute allows us to output variable values from a class or method to be displayed in our Visual Studio debugger. The attribute includes a single argument that is supplied as a string. The string can contain references to fields, properties and methods in the class so that the actual values from an object may be included in its description.

    [DebuggerDisplay("a={a}, b={b}, ValueTotal={CalculateValues()}")]
    public class AddValues
    {    
        public int a { get; set; }
        public int b { get; set; }
        
        public int CalculateValues()
        {
            return a + b;
        }
    }
    

    You also have the ability to include simple expressions, like so:

    [DebuggerDisplay("a={a}, b={b}, ValueTotal={CalculateValues() * 2}")]
    

    In addition to the “DebuggerHidden” and DebuggerDisplay attributes, .NET contains some very useful attributes that modify the behaviour of a debugger. For me, they weren’t as interesting as the two debugger attributes I listed above. :-)

  • crying-man Last week my blog was offline due to an unfortunate mishap. I won’t go into the details on what happened. I’d rather just forget.

    After a lot of hard work, sweat and tears, my blog is almost back to its former glory. I was lucky enough to find a backup that was made a few months ago using BlogEngine’s BlogML export tool. Hooray!

    Even though all my posts are back on display, I have unfortunately lost some user comments and ratings. It saddens me to know that I have lost this valuable information, since hearing your thoughts makes this blog a more exciting read.

    There is still some work to do, but I am glad to say the difficult part is over.

  • Will IE6 Ever Allows Us To Use CSS3 We have been using Cascading Style Sheets for many years now and it has been a god send to help break us away from table based layouts and create an aesthetically pleasing site. I was quite surprised to find out that the CSS 2.1 standard has been around for 11 years. We have moved on considerably over this duration of time and even though some recent browsers are adopting CSS3 already, why do we continue to use CSS2.1?

    The only answer to this question I can think of is due to the continued use of legacy browsers such as IE6. If we look at the current browser trends (below), the amount of IE6 users have decreased over the year from 18.5% to 14.4%. So this is a decrease by around 4%, which is good but not great.

    2009 IE7 IE6 IE8 Firefox Chrome Safari Opera
    July 15.9% 14.4% 9.1% 47.9% 6.5% 3.3% 2.1%
    June 18.7% 14.9% 7.1% 47.3% 6.0% 3.1% 2.1%
    May 21.3% 14.5% 5.2% 47.7% 5.5% 3.0% 2.2%
    April 23.2% 15.4% 3.5% 47.1% 4.9% 3.0% 2.2%
    March 24.9% 17.0% 1.4% 46.5% 4.2% 3.1% 2.3%
    February 25.4% 17.4% 0.8% 46.4% 4.0% 3.0% 2.2%
    January 25.7% 18.5% 0.6% 45.5% 3.9% 3.0% 2.3%
                   

    (http://www.w3schools.com)

    Looking back at all the sites I have created over the year, I still find myself applying workarounds to give IE6 and current browsers the same viewing experience. So 14.4% of IE6 users still has a major impact on general web design.

    Generally, companies are probably to blame for the continued use of IE6. Big companies are sometimes slow to change and especially if using the web is not at the business core they don’t see any reason to move forward. In addition, they see IE6 as a more secure browser.

    Can I see a final nail in the IE6 coffin sometime in the future? Unfortunately, No. Microsoft have extended their support for IE6 to 2014. So for now IE6 users still have 5 years to upgrade. Lets just hope Microsoft doesn’t make the same mistake and renew IE6 support for another 5 years after 2014!

    We as users of the Internet need to move with the time. If we don’t, sites will continue to be restricted to the confines of yesteryear which is no good to anybody. Legacy browsers such as IE6 need to be phased out via end of life programmes and allow newer browsers to flourish.

  • I upgraded to the really cool BlogEngine 1.5 last week. I was surprised to find out that I was three versions behind. Nevertheless, the guys behind BlogEngine always know how the make the upgrade really easy!

    When I tried to publish a blog posting using Windows Live Writer, I came across two problems. The first problem I had was the dreaded “Object reference not set to an instance of an object” error. I really hate this error! This has to be the most useless error message in .NET!

    The second problem I came across was the inability to upload images and the following error occurred:

    WLWImageUploadError

    After some good old research on the web and reading various BlogEngine Discussion forums, fixing these errors is as straight-forward as installing BlogEngine.

    To fix the “Object reference not set to an instance of an object” error all you have to do is create a new blog account in Windows Live Writer. Just updating your account configuration will not resolve this issue. You have to setup a new account. I think this will update the wlwmanifest.xml file in your site directory. Once you have successfully tested you can publish a blog post with your new account, delete your old account.

    The image upload issue is caused by permissions restrictions to your App_Data folder. Make sure you have allowed read/write permissions to this folder. For some reason adding read/write permissions to the App_Data folder through my FTP client did not work. The only way I was able to set the permissions is through my Hosting Plan File Manager account.

  • firefly When the mobile phone first came out, not surprisingly they took the world by storm. Over the years, the mobile has evolved and it was only going to be a matter of time before a phone for a child would be released.

    The Firefly mobile phone for four-year-olds has the ability to take pictures, video’s and play MP3 files while allowing parents to have full control. They can restrict who can be called from the phone, who can call the phone and control how much is spent. This is all well and good, but I am finding quite hard to understand why a child of four would ever need a mobile? Isn’t it the parents, teachers or guardians responsibility to ensure that the child is safe? Targeting a mobile phone for four-year-olds raises the question on where the parents responsibility is going.

    I remember back in the good old days when I was a kid, my parents were definitely the over-protected type (and they still are). But they always made sure they knew my whereabouts and I was always in the company of an responsible adult to keep an eye over my mischievous ways. Have things changed so much since I was a young kid (I am 24 now) that there is now a need for toddlers to have mobiles? The answer is NO! Only the bank balance of mobile phone companies will be benefiting from this idea.

    I have to admit the Firefly mobile phone makers have a very clever marketing team. They are just playing on the fear that all parents have. Losing sight of their child. If you don’t know where your four-year-old is, will he/she know? Four-year-olds rarely have information to impart of such significance on their surroundings that will help in locating where they are.

    We have all been made aware of the health concerns on the impact of mobile phone radiation. We as adults know the consequences of prolonged use a mobile phone can have on our brains and have the freedom of choice to decide how long we wish use them. What about a child? They do not have the knowledge to make such a choice? A disturbing study by researchers at Örebro University Hospital in Sweden last year indicated that children may be five times more likely to get brain cancer if they use mobile phones.

    I could carry on moaning about this mobile phone. I can see no reason a child young as four to have a mobile phone.

  • Ok! I admit it! I posted some incorrect information from one of my previous blog posts to “Dynamically Output A List of YouTube Video’s In ASP.NET”. I stupidly said: “The RSS feed is not structured in a nice enough format to output all the information you may need with ease.” I must have been drunk when I wrote that. As you can see from a sample of their RSS feed below I was wrong:

    <entry>
      <id>http://gdata.youtube.com/feeds/api/videos/R6r2ckeIpic</id>
        <published>2009-05-31T17:01:12.000Z</published>
        <updated>2009-06-01T01:22:11.000Z</updated>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='bike'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Podcast'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Pedrosa'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='motorcycles'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Honda+RC212V'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='speed'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Suzuki+GSV-R800'/>
        <category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#video'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' term='Sports' label='Sport'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Rossi'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='motorcycle+road+racing'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='motograndprix'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Yamaha+YZR+M1'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Mugello'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Italy'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Stoner'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Ducati+Desmosedici+GP8'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='MotoGP'/>
        <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='Lorenzo'/>
        <title type='text'>MotoGP action from Mugello 2009</title>
        <content type='text'>The best of the action from the Gran Premio D&amp;#180;Italia Alice, the fifth round of the 2009 motogp World Championship.</content>
        <link rel='alternate' type='text/html' href='http://www.youtube.com/watch?v=R6r2ckeIpic'/>
        <link rel='http://gdata.youtube.com/schemas/2007#video.responses' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/R6r2ckeIpic/responses'/>
        <link rel='http://gdata.youtube.com/schemas/2007#video.related' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/R6r2ckeIpic/related'/>
        <link rel='self' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/users/motogp/uploads/R6r2ckeIpic'/>
        <author>
          <name>MotoGP</name>
          <uri>http://gdata.youtube.com/feeds/api/users/motogp</uri>
        </author>
        <gd:comments>
          <gd:feedLink href='http://gdata.youtube.com/feeds/api/videos/R6r2ckeIpic/comments' countHint='24'/>
        </gd:comments>
        <media:group>
          <media:category label='Sport' scheme='http://gdata.youtube.com/schemas/2007/categories.cat'>Sports</media:category>
          <media:description type='plain'>The best of the action from the Gran Premio D&amp;#180;Italia Alice, the fifth round of the 2009 motogp World Championship.</media:description>
          <media:keywords>MotoGP, Italy, Mugello, Podcast, Stoner, Pedrosa, Rossi, Lorenzo, Yamaha+YZR+M1, Ducati+Desmosedici+GP8, Honda+RC212V, Suzuki+GSV-R800, motorcycle+road+racing, motograndprix, motorcycles, bike, speed</media:keywords>
          <media:player url='http://www.youtube.com/watch?v=R6r2ckeIpic'/>
          <media:thumbnail url='http://i.ytimg.com/vi/R6r2ckeIpic/2.jpg' height='90' width='120' time='00:00:38.500'/>
          <media:thumbnail url='http://i.ytimg.com/vi/R6r2ckeIpic/1.jpg' height='90' width='120' time='00:00:19.250'/>
          <media:thumbnail url='http://i.ytimg.com/vi/R6r2ckeIpic/3.jpg' height='90' width='120' time='00:00:57.750'/>
          <media:thumbnail url='http://i.ytimg.com/vi/R6r2ckeIpic/0.jpg' height='240' width='320' time='00:00:38.500'/>
          <media:title type='plain'>MotoGP action from Mugello 2009</media:title>
          <yt:duration seconds='77'/>
        </media:group>
        <yt:noembed/>
        <gd:rating average='4.862069' max='5' min='1' numRaters='29' rel='http://schemas.google.com/g/2005#overall'/>
        <yt:statistics favoriteCount='10' viewCount='1055'/>
    </entry>
    <entry>
        ...
    </entry>
    <entry>
        ...
    </entry>
    

    Each “entry” element within the RSS feed represents a YouTube video. You are able to extrapolate all the important information about each movie such as Average Score, View Count, Thumbnail Images, Video Description, etc. Really useful stuff!

    You may be thinking: Why should I use an RSS feed to retrieve the video information rather than using the YouTube API? Well, using a YouTube API is definitely the easier and most straight-forward method. But what you should be aware that the API only works from .NET 2.0 onwards. There isn’t a YouTube API for .NET 1.1. Unfortunately, I only found this out when I tried to implement the API into one of my .NET 1.1 client sites.

    The code I have written below, reads the YouTube RSS feed and stores the information in a DataTable.

    private void GetYouTubeData(string YouTubeUrl)
    {
        //Create DataTable to store specific YouTube information
        DataTable dtYouTubeVideoData = new DataTable();
        dtYouTubeVideoData.Columns.Add("YouTubeID");
        dtYouTubeVideoData.Columns.Add("Title");
        dtYouTubeVideoData.Columns.Add("Description");
        dtYouTubeVideoData.Columns.Add("ImageUrl");
        dtYouTubeVideoData.Columns.Add("AverageRatings");
        dtYouTubeVideoData.Columns.Add("ViewCount");
    
        DataRow drYouTubeVideoData;
    
        //Link to YouTube RSS feed
        XmlTextReader rssReader = new XmlTextReader(YouTubeUrl);
        XmlDocument xmlDoc = new XmlDocument();
    
        //Download the XML (via the XmlTextReader)
        xmlDoc.Load(rssReader);
    
        //Select all nodes starting with "entry"
        XmlNodeList xmlNodeList = xmlDoc.GetElementsByTagName("entry");
        
        //For each "entry" element found
        foreach (XmlNode node in xmlNodeList)
        {
            drYouTubeVideoData = dtYouTubeVideoData.NewRow();
    
            //Create a new document, to search through the inner contents
            XmlDocument innerXmlDocument = new XmlDocument();
            innerXmlDocument.LoadXml(node.OuterXml);
    
            // Get movie ID
            drYouTubeVideoData["YouTubeID"] = innerXmlDocument.GetElementsByTagName("id")[0].InnerText.Replace("http://gdata.youtube.com/feeds/api/videos/", "");
    
            // Get movie title
            drYouTubeVideoData["Title"] = innerXmlDocument.GetElementsByTagName("title")[0].InnerText;
    
            //Get movie description
            drYouTubeVideoData["Description"] = innerXmlDocument.GetElementsByTagName("content")[0].InnerText;
            
            //Get the thumbnails
            XmlNodeList mediaTumbnail = innerXmlDocument.GetElementsByTagName("media:thumbnail");
    
            //Iterate through each thumbnail and only get one thumbnail per <entry>.
            foreach (XmlNode thumbnailNode in mediaTumbnail)
            {
                if (thumbnailNode.Attributes["height"].Value == "90" && thumbnailNode.Attributes["url"].Value.EndsWith("1.jpg"))
                {
                    drYouTubeVideoData["ImageUrl"] = thumbnailNode.Attributes["url"].Value;
                }
            }
    
            //Get movie rating
            XmlNodeList ratings = innerXmlDocument.GetElementsByTagName("gd:rating");
    
            foreach (XmlNode ratingsNode in ratings)
            {
                drYouTubeVideoData["AverageRatings"] = ratingsNode.Attributes["average"].Value;
            }
    
            //Get Statistics
            XmlNodeList statistics = innerXmlDocument.GetElementsByTagName("yt:statistics");
    
            foreach (XmlNode statisticsNode in statistics)
            {
                drYouTubeVideoData["ViewCount"] = statisticsNode.Attributes["viewCount"].Value;
            }
    
            dtYouTubeVideoData.Rows.Add(drYouTubeVideoData);
        }
    
        rssReader.Close();
    
        //Bind YouTube data to repeater
        repVideoList.DataSource = dtYouTubeVideoData;
        repVideoList.DataBind();        
    }
    
  • BrowserRefresh Being a fellow Web Developer, you would probably agree with me when I say that the “Refresh” button is the most used button in your browser. I can’t even consider about counting the amount of times I hit the “Refresh” button while creating a web page.

    On the odd occasion when I am having a really bad day and nothing seems to be going my way. I am bound to be irritated even further because my browser is being really stupid and does not allow me to see the changes I have made to a web page I am working on. Its almost like the browser is trying to mock me and make my web developing life and living HELL!!!!!

    So I carry out the following methods to get my page to refresh.

    Force Refresh

    In many cases in order to see changes on your page you would press the “Refresh” button (or F5), which simply reloads the page without clearing the cache. So you will have to carry out a Force Refresh by pressing Ctrl + F5.

    Clearing Cache In Settings

    If the Force Refresh does not work. You will have to carry out some serious cleaning by going into the browser settings.

    • Mozilla FireFox – Tools > Options > Privacy > Private Data section > Settings
    • Microsoft Internet Explorer – Tools > Internet Options > Temporary Files > Delete Temporary Files

    Adding “?” To End of The WEB address

    This is probably my most favourite method of ensuring a page you are viewing is not cached. All you need to do is add a “?” to the end of the web address. For example:

    ?
    

    The browser thinks that you are requesting a new page. This works great if all else fails! You can even add another “?” to the end of the web address to carry out another non-cached refresh.