<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4436884927968508267</id><updated>2012-01-02T06:55:48.416Z</updated><category term='url'/><category term='datasource'/><category term='control'/><category term='strange'/><category term='support'/><category term='solution'/><category term='introduction'/><category term='javascript'/><category term='logs'/><category term='linkbutton'/><category term='states'/><category term='add'/><category term='gridview'/><category term='input'/><category term='event'/><category term='tag'/><category term='http'/><category term='upgrade'/><category term='service'/><category term='rollovers'/><category term='script manager'/><category term='query'/><category term='form'/><category term='datarepeater'/><category term='page_loadcomplete'/><category term='c#'/><category term='shrink'/><category term='firefox'/><category term='test'/><category term='closing'/><category term='datalist'/><category term='duplicate'/><category term='css'/><category term='plugin'/><category term='cms'/><category term='attributes'/><category term='class'/><category term='fm'/><category term='fundemental'/><category term='zen'/><category term='episerver 5'/><category term='.net'/><category term='individual'/><category term='customise'/><category term='openpop pop3 connect asp.net c# xml attachment'/><category term='page_prerender'/><category term='anchor'/><category term='asp'/><category term='navigate'/><category term='lower case'/><category term='element'/><category term='transaction'/><category term='early'/><category term='last'/><category term='301'/><category term='datatable'/><category term='internet explorer'/><category term='ajax'/><category term='stream'/><category term='cells'/><category term='field'/><category term='dataset'/><category term='indexing'/><category term='format'/><category term='enableHistory'/><category term='sql server'/><category term='page'/><category term='creative'/><category term='jquery'/><category term='umbraco'/><category term='hidden'/><category term='episerver'/><category term='audioscrobbler'/><category term='edit'/><category term='redirection'/><category term='problems'/><category term='databind'/><category term='styles'/><category term='ammend'/><category term='tab control'/><category term='lack'/><category term='call'/><category term='2.0'/><category term='view'/><category term='div'/><category term='asp.net'/><category term='episerver 6'/><category term='setattribute'/><category term='content'/><category term='data'/><category term='update panel'/><category term='hover'/><title type='text'>Coding Rage</title><subtitle type='html'>My name's Karl Alesbury, and I'm an ASP.NET web developer based in Bristol, UK.

This blog is an attempt to sort out my coding gremlins or to post solutions on ridding the world of them.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-1262054868304791441</id><published>2011-07-29T11:03:00.000+01:00</published><updated>2011-07-29T11:03:08.898+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='redirection'/><category scheme='http://www.blogger.com/atom/ns#' term='duplicate'/><category scheme='http://www.blogger.com/atom/ns#' term='url'/><category scheme='http://www.blogger.com/atom/ns#' term='lower case'/><category scheme='http://www.blogger.com/atom/ns#' term='301'/><category scheme='http://www.blogger.com/atom/ns#' term='page'/><category scheme='http://www.blogger.com/atom/ns#' term='content'/><title type='text'>Avoiding duplicate content due to case-sensitive URLs</title><content type='html'>A point that's been raised a fair bit recently by SEO specialists I work with is duplicate page content. This happens when you're using URL rewriting to point a URL to a page, and there is more than one way to get to that content.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;br /&gt;http://www.website.com/news&lt;br /&gt;and&lt;br /&gt;http://www.website.com/news/home&lt;br /&gt;&lt;br /&gt;Could both lead to the same place. Google crawls both of these URLs, and distinguishes them as separate. This can allegedly affect your ranking, and as a result, it's good to have your duplicate URL 301 redirect to the other.&lt;br /&gt;&lt;br /&gt;This is also the case with URL rewriting case-sensitive URLs:&lt;br /&gt;&lt;br /&gt;http://www.website.com/ThisURL&lt;br /&gt;and&lt;br /&gt;http://www.website.com/thisurl&lt;br /&gt;&lt;br /&gt;A lot of regular expression matching URL rewriters such as &lt;a href="http://urlrewriter.net/" target="_blank"&gt;URLRewriter.NET&lt;/a&gt; will happily handle both URLs and point you to the same page content. To get around this, I've implemented some code in the global.asax file to convert URLs to all lower-case.&lt;br /&gt;&lt;br /&gt;http://www.website.com/ThisURL&lt;br /&gt;&lt;br /&gt;will be checked in the global.asax file, and a 301 redirect will send you to:&lt;br /&gt;&lt;br /&gt;http://www.website.com/thisurl&lt;br /&gt;&lt;br /&gt;There's one other thing to bare in mind; ASP.NET's built-in AJAX functionality requires you to have some references to AXD files such as scriptresource.axd and webresource.axd. These files have case-sensitive querystrings, and if you don't add an exception for AXD files, these files won't be reachable, and your AJAX controls will no longer work.&lt;br /&gt;&lt;br /&gt;Finally, you also have to ensure that you don't get in the way of postbacks. If you don't distinguish between a postback and a standard URL request, your postbacks will no longer work, and all your forms will break.&lt;br /&gt;&lt;br /&gt;If you check out the code sample below, you'll see that I've ensured that only GET requests are checked, and that AXD files are excluded.&lt;br /&gt;&lt;code class="prettyprint"&gt;&lt;br /&gt;protected void Application_BeginRequest(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        //If upper case letters are found in the URL, redirect to lower case URL.&lt;br /&gt;        if (Regex.IsMatch(HttpContext.Current.Request.RawUrl.ToString(), @"[A-Z]") == true)&lt;br /&gt;        {&lt;br /&gt;if (Request.HttpMethod == "GET" &amp;amp;&amp;amp; !(Request.RawUrl.Contains(".axd")))&lt;br /&gt;             {&lt;br /&gt;            string LowercaseURL = HttpContext.Current.Request.RawUrl.ToString().ToLower();&lt;br /&gt;            Response.Clear();&lt;br /&gt;            Response.Status = "301 Moved Permanently";&lt;br /&gt;            Response.AddHeader("Location", LowercaseURL);&lt;br /&gt;            Response.End();&lt;br /&gt;}&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-1262054868304791441?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/1262054868304791441/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=1262054868304791441' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/1262054868304791441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/1262054868304791441'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2011/07/avoiding-duplicate-content-due-to-case.html' title='Avoiding duplicate content due to case-sensitive URLs'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-5132368902298328952</id><published>2011-07-04T09:00:00.000+01:00</published><updated>2011-07-04T09:00:02.379+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='event'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='navigate'/><category scheme='http://www.blogger.com/atom/ns#' term='enableHistory'/><category scheme='http://www.blogger.com/atom/ns#' term='script manager'/><title type='text'>The Script Manager enableHistory attribute</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Overview&lt;/span&gt;&lt;br /&gt;&lt;a href="http://geekswithblogs.net/frankw/archive/2008/10/29/enable-back-button-support-in-asp.net-ajax-web-sites.aspx" target="_blank"&gt;Geeks with blogs&lt;/a&gt; have produced a lovely blog that'll show you how to set up your page's script manager to allow your back and forward browser buttons to trigger an event.&lt;br /&gt;&lt;br /&gt;It runs through how to enable it using the enableHistory attribute on the script manager and how to wire up the event so that when you use the back buttons it'll fire.&lt;br /&gt;&lt;br /&gt;Something that's worth pointing out though, is that you &lt;strong&gt;MUST&lt;/strong&gt; add a history point during a postback event before leaving the page, or your event won't be fired. This may seem obvious, but I didn't realise!&lt;br /&gt;&lt;br /&gt;So you'll definitely need a line like this in a postback event:&lt;br /&gt;&lt;br /&gt;ScriptManager1.AddHistoryPoint("Key", "Value");&lt;br /&gt;&lt;br /&gt;Without that happening at least once before leaving the page, your navigate event won't fire.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-5132368902298328952?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/5132368902298328952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=5132368902298328952' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/5132368902298328952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/5132368902298328952'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2011/07/script-manager-enablehistory-attribute.html' title='The Script Manager enableHistory attribute'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-4948358172114157382</id><published>2011-06-28T12:26:00.005+01:00</published><updated>2011-06-28T12:32:06.487+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cms'/><category scheme='http://www.blogger.com/atom/ns#' term='update panel'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='umbraco'/><category scheme='http://www.blogger.com/atom/ns#' term='episerver'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='tab control'/><title type='text'>A .NET tab list control for content managed sites</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Most websites these days seem to contain tabbed content; it's a way for more information to be displayed on a page whilst still technically being above the fold, and it's historically been a very good way of organising and pooling content together. However, having a tabbed layout on your website can create a few problems too, such as:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;How search spiders crawl your content&lt;/li&gt;&lt;li&gt;How you URL-rewrite your content so that you can drop users onto a specific page with a specific tab pre-selected for them to look at.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Possible solutions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;How tabs are handled from an ASP.NET technical perspective depends largely on the content that you're displaying.&lt;br /&gt;&lt;br /&gt;In some cases, tabbed content is minimal in size, and you can get away with creating a very fast user interface by pulling all of the content for each tab in on the preload, and then showing and hiding the containers holding the content.&lt;br /&gt;&lt;br /&gt;In this case, if you have five tabs, you could create five hidden divs and show or hide them depending on which tab has been clicked. This approach also has the benefit of allowing search spiders to crawl all of your tabbed information in one hit, as it's held in one page.&lt;br /&gt;&lt;br /&gt;In other cases, sites will need several tabs, each containing a LOT of content. In cases like these, it's better to call this information when it's required, ie when a user has clicked on the tab they want to see. In cases like these, it's better to pull the content in using AJAX (be it via JQuery, or via .NET update panels). I'm choosing update panels.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Pre-selecting your tab&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A good idea to begin with, is that when you enter a URL such as&lt;br /&gt;&lt;br /&gt;/this-page?tab=your-tab-name-here&lt;br /&gt;&lt;br /&gt;Your tab should be automatically selected and loaded in. This allows users a method of getting straight into a particular part of your content, and the tabs aren't an obstruction. You can do this by checking the URL you came in on in the page_load event, and popping your active tab in the update panel.&lt;br /&gt;&lt;br /&gt;&lt;div id='iframeDiv0bdd185c-434b-4cdd-9b83-af9fd18ac99d' style='display:none;margin:0px;'&gt;&lt;iframe id='iframe0bdd185c-434b-4cdd-9b83-af9fd18ac99d' src='http://www.blogtrog.com/code.aspx?id=0bdd185c-434b-4cdd-9b83-af9fd18ac99d' style='width: 400px; height: 200px; border: 1px solid #e0e0e0;margin:0px;' frameborder='0'&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div id='noIframeDiv0bdd185c-434b-4cdd-9b83-af9fd18ac99d' style='display:block;margin:0px;'&gt;&lt;pre&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;Page.IsPostBack)&lt;br /&gt;{&lt;br /&gt;  hidValue.Value &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;).ToString();&lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (Request.Params[&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Tab&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;  {&lt;br /&gt;      TabName &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; Request.Params[&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Tab&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;].ToString();&lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;ContentPageId is a global integer to hold the ID of my tab&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;         hidValue.Value &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; ContentPageId.ToString();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;{&lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;on postback set content type to hidden field value&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;     ContentPageId &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; Int16.Parse(hidValue.Value);&lt;br /&gt;}&lt;br /&gt;Repeater1.DataBind();&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;script language='javascript' src='http://www.blogtrog.com/scripts/bt_code.js' type='text/javascript'&gt;&lt;/script&gt;&lt;script language='javascript' type='text/javascript'&gt;bt_code_init('0bdd185c-434b-4cdd-9b83-af9fd18ac99d');&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;We call the databind method for the Repeater1 object because that's what's binding our tabs to our update panel. The repeater will grab the ContentPageId, determine what tab you want to show, and set that as the active tab accordingly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Binding our clickable tabs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Each tab within the repeater has a href with a link of /?tab=your-tab-name-here, and an onclick attribute that fires a javascript function that updates a hidden input value which will hold the ID that you can use to reference your content. This attribute then returns false so as not to get the href to fire.&lt;br /&gt;&lt;br /&gt;So your javascript function might look something like this:&lt;br /&gt;&lt;br /&gt;&lt;div id='iframeDiv70667d9f-c00f-4acc-91a8-4fd50d70953d' style='display:none;margin:0px;'&gt;&lt;iframe id='iframe70667d9f-c00f-4acc-91a8-4fd50d70953d' src='http://www.blogtrog.com/code.aspx?id=70667d9f-c00f-4acc-91a8-4fd50d70953d' style='width: 400px; height: 200px; border: 1px solid #e0e0e0;margin:0px;' frameborder='0'&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div id='noIframeDiv70667d9f-c00f-4acc-91a8-4fd50d70953d' style='display:block;margin:0px;'&gt;&lt;pre&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; SetHidValue(value) {&lt;br /&gt;document.getElementById(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;hiddenInput&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;).value &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; value;&lt;br /&gt;document.getElementById(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;SubmitButton&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;).click();&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;script language='javascript' src='http://www.blogtrog.com/scripts/bt_code.js' type='text/javascript'&gt;&lt;/script&gt;&lt;script language='javascript' type='text/javascript'&gt;bt_code_init('70667d9f-c00f-4acc-91a8-4fd50d70953d');&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Each anchor tag in the repeater will look something like this:&lt;br /&gt;&lt;br /&gt;&lt;div id='iframeDiv1a6213dd-ee13-43a3-92b4-8bc89c650754' style='display:none;margin:0px;'&gt;&lt;iframe id='iframe1a6213dd-ee13-43a3-92b4-8bc89c650754' src='http://www.blogtrog.com/code.aspx?id=1a6213dd-ee13-43a3-92b4-8bc89c650754' style='width: 400px; height: 200px; border: 1px solid #e0e0e0;margin:0px;' frameborder='0'&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div id='noIframeDiv1a6213dd-ee13-43a3-92b4-8bc89c650754' style='display:block;margin:0px;'&gt;&lt;pre&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;a &lt;/span&gt;&lt;span style="color: #FF0000;"&gt;href&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;=&amp;quot;/?tab=your-tab-here&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; onclick&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;=&amp;quot;javascript:setHidValue(14)&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Tab title&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;script language='javascript' src='http://www.blogtrog.com/scripts/bt_code.js' type='text/javascript'&gt;&lt;/script&gt;&lt;script language='javascript' type='text/javascript'&gt;bt_code_init('1a6213dd-ee13-43a3-92b4-8bc89c650754');&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Where the argument passed into setHidValue() is the dynamically populated ID of the tab you're after. The methodology of using tab IDs is required in my case because I'm using a content management solution (It could be EPiServer or Umbraco for example), which will require a page ID to grab the relevant page object when I know which tab has been asked for.&lt;br /&gt;&lt;br /&gt;Our click() event in the javascript function fires a submit button that'll trigger a postback within the scope of the update panel. Your page_load should then check to see if you've got a hidden input value, and if so, you know which tab to show. If you don't have one, the second choice should be your tab= querystring parameter.&lt;br /&gt;&lt;br /&gt;What this means, is if you don't have javascript (or you're a search spider and you want to crawl individual tabs without the help of javascript), you can use the querystring URLs instead.&lt;br /&gt;&lt;br /&gt;This post is going to end up being quite complicated, so if you have any suggestions or questions, please pop them in a comment, and I'll try to address them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-4948358172114157382?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/4948358172114157382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=4948358172114157382' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/4948358172114157382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/4948358172114157382'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2011/06/net-tab-list-control-for-content.html' title='A .NET tab list control for content managed sites'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-6308732222220688589</id><published>2011-06-20T10:11:00.002+01:00</published><updated>2011-06-20T10:11:00.216+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql server'/><category scheme='http://www.blogger.com/atom/ns#' term='episerver 6'/><category scheme='http://www.blogger.com/atom/ns#' term='episerver'/><category scheme='http://www.blogger.com/atom/ns#' term='upgrade'/><category scheme='http://www.blogger.com/atom/ns#' term='episerver 5'/><title type='text'>Upgrading an EPiServer CMS 5 site to EPiServer CMS 6</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've built a few websites in the EPiServer CMS now, and because I've developed those websites in quick succession, I have rarely needed to use the deployment center's upgrade wizard.&lt;br /&gt;&lt;br /&gt;I've recently had to upgrade an EPiServer site from version 5R2SP1 to version 6, and had to initally provide a scope for any areas that might go wrong.&lt;br /&gt;&lt;br /&gt;The upgrade wizard's upgrade process makes changes to the EPiServer database, adds some extra files to the site's /bin/ directory, and also makes some fairly significant changes to the web.config.&lt;br /&gt;&lt;br /&gt;Changes to the file system are quite easy to spot (the upgrade wizard produces a log file for your perusal), but the major issue that I encountered with upgrading was changes made to the database.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The problem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When hosting an EPiServer website on one server and the database on a separate server, the upgrade wizard must make modifications to the data on both servers. The upgrade wizard is part of the deployment center, and so changes to the filesystem were done with no problem. However, the upgrade wizard kept throwing an error complaining that it couldn't connect to the database, and that authentication failed. This is because unless your servers are hosted on the same domain, your windows account is unlikely to be authenticated. Regardless of whether you specify windows authentication or sql authentication with the SA password, you'll get the same problem.&lt;br /&gt;&lt;br /&gt;There are two main methods for working around this problem, namely a manual upgrade using SQL scripts, or the method I chose.&lt;br /&gt;&lt;br /&gt;For the manual upgrade, you can see Bjorn Isaksen's blog on it here:&lt;br /&gt;&lt;a href="http://baisaksen.net/episerver/upgrade-episerver-database-manually-5-6" target="_blank"&gt;Upgrade EPiServer database manually from 5 to 6&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The solution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The method I chose was to do the following:&lt;br /&gt;&lt;br /&gt;1) Ensure a code and CMS freeze to ensure that no data is updated and no content is updated during the upgrade.&lt;br /&gt;&lt;br /&gt;2) Take a copy of the live database, and restore it to our development server.&lt;br /&gt;&lt;br /&gt;3) Take a copy of the latest development code, happy that this is a codeset you're okay to go live with.&lt;br /&gt;&lt;br /&gt;4) Set this copy of the code up in IIS as a separate EPiServer site.&lt;br /&gt;&lt;br /&gt;5) Point the connection strings in that copy to point to your newly restored EPiServer database.&lt;br /&gt;&lt;br /&gt;6) Run the upgrade wizard, following the prompts and ensuring that the upgrade's successful.&lt;br /&gt;&lt;br /&gt;7) Publish the newly modified code (whether you export that from your source control directory, or build it manually, it's up to your current development process model).&lt;br /&gt;&lt;br /&gt;8) Attach the new database from your development site to the user acceptance testing database server (essentially your backup copy of the live site). I restored this to a fresh database so that I could have a clean swap in the connectionstrings.config file.&lt;br /&gt;&lt;br /&gt;9) Upload the code to the user acceptance testing development server.&lt;br /&gt;&lt;br /&gt;10) Change the connectionstrings.config file to point to your newly restored database.&lt;br /&gt;&lt;br /&gt;I then tested the functionality of the site to ensure that everything was behaving as it should, and hey presto! One upgraded site!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Reference&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For further information on the upgrade process and what's involved in the filesystem changes, you can see Fredrik Haglund's blog here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.fredrikhaglund.se/blog/2010/03/10/configuration-management-and-episerver-cms-6/" target="_blank"&gt;Configuration management and EPiServer CMS 6&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-6308732222220688589?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/6308732222220688589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=6308732222220688589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/6308732222220688589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/6308732222220688589'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2011/04/upgrading-episerver-cms-5-site-to.html' title='Upgrading an EPiServer CMS 5 site to EPiServer CMS 6'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-7840925280210439610</id><published>2011-06-13T10:49:00.007+01:00</published><updated>2011-06-13T16:38:36.986+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='logs'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server'/><category scheme='http://www.blogger.com/atom/ns#' term='transaction'/><category scheme='http://www.blogger.com/atom/ns#' term='shrink'/><title type='text'>Shrinking the transaction logs for a SQL Server database</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Bare in mind that shrinking log files is not the same as compressing SQL Backups. It's important to note this, because if you Google for each, you'll return different results.&lt;br /&gt;&lt;br /&gt;Compressing SQL Backups is the act of compressing *.bak files that are backups of the database itself.&lt;br /&gt;&lt;br /&gt;Shrinking SQL Log files is the act of removing transaction logs that you don't want anymore; essentially, you are removing unwanted transactions from the database's .LDF file.&lt;br /&gt;&lt;br /&gt;I've worked on a few projects that pull in several million visitors per week, where the database server has hardly any disk space left due to large transaction log files that don't need to be there in this business case.&lt;br /&gt;&lt;br /&gt;FYI, I gathered the information to do this from this Microsoft article: &lt;a href="http://support.microsoft.com/kb/907511" target="_blank"&gt;http://support.microsoft.com/kb/907511&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The process&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are two commands that have to be executed, which are explained below with an example database.&lt;br /&gt;&lt;br /&gt;1) backup log dbTestDatabase to disk = 'C:\SQL\Backups\dbTestDatabaseLogs.bak'&lt;br /&gt;&lt;br /&gt;This command is backing up your transaction log to a .bak file. In the process of doing this, the virtual logs that are in use by the DMBS are freed up after they're backed up. This then allows you to do step 2.&lt;br /&gt;&lt;br /&gt;2) DBCC SHRINKFILE ('dbTestDatabase_Log', 1) WITH NO_INFOMSGS&lt;br /&gt;&lt;br /&gt;This means that you're going to shrink the logical name for the dbTestDatabase.ldf file to 1mb and you don't want messages back. To get this name, right-click on your database, and choose properties. Then click "Files", and your logical name is shown on the row with the file type of "log".&lt;br /&gt;&lt;br /&gt;This command removes the virtual logs that you've just backed up. If you run this command without running the backup first, you won't get the LDF file down to your desired size, as the DBMS will still be using a lot of the transactions you're trying to remove.&lt;br /&gt;&lt;br /&gt;If you still can't get the log file down to your desired file size, a few virtual transactions may have piled up in the meantime, so run step one again, and then re-run step 2 quickly afterwards.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-7840925280210439610?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/7840925280210439610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=7840925280210439610' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/7840925280210439610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/7840925280210439610'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2011/06/shrinking-transaction-logs-for-sql.html' title='Shrinking the transaction logs for a SQL Server database'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-5592562817033996104</id><published>2009-05-11T17:17:00.004+01:00</published><updated>2009-06-25T09:58:16.654+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='tag'/><category scheme='http://www.blogger.com/atom/ns#' term='early'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='closing'/><title type='text'>Firefox and form tags</title><content type='html'>Here's one for you.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you have a table layout with form elements within it, make sure you place the form tags outside the table altogether. Put them just inside the body tag if you can.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was putting form tags within table tags, and it was causing the form to close itself prematurely.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was using javascript to render the form elements, and when looking at the generated source, I saw that firefox was closing the form tag early.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It works okay within IE 8, though it breaks in Chrome and Firefox.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let that be a lesson to you. It certainly was for me!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-5592562817033996104?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/5592562817033996104/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=5592562817033996104' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/5592562817033996104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/5592562817033996104'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2009/05/firefox-and-form-tags.html' title='Firefox and form tags'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-4995328275949799584</id><published>2008-04-11T15:16:00.002+01:00</published><updated>2008-04-11T15:24:55.470+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='openpop pop3 connect asp.net c# xml attachment'/><title type='text'>Fetching and processing POP3 email in C#.NET</title><content type='html'>This is a problem that plagued the first three hours of my day, and was solved by the incredibly handy &lt;a target="_blank" href="http://sourceforge.net/projects/hpop/"&gt;OpenPop.NET&lt;/a&gt;. I played with two other POP-related products including one entry on TheCodeProject.com, but with not much in the way of luck.&lt;br /&gt;&lt;br /&gt;I was really impressed with OpenPop.NET because I was able to create a POP3 solution that:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Connected to a POP server.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Fetched some email.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Checked the attachments for the ContentType of text/xml.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;If it was XML, I then processed and saved the XML to disk.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;All of the above took a grand total of 60 minutes to complete, and all of this was without any documentation (I think it's a side-project of two developers who haven't gotten around to documenting it yet), which speaks volumes for the simplicity of its design and the properties and methods it exposes.&lt;br /&gt;&lt;br /&gt;Source code is below just in case you get stuck. Obviously you'll need to introduce some error trapping.&lt;br /&gt;&lt;br /&gt;OpenPOP.POP3.POPClient client = new POPClient("pop.1and1.co.uk", 110, "shiptrack@yucca.co.uk", "shiptrack", AuthenticationMethod.USERPASS);      &lt;br /&gt;        if (client.Connected) {&lt;br /&gt;            int msgCount = client.GetMessageCount();&lt;br /&gt;&lt;br /&gt;            /* Cycle through messages */&lt;br /&gt;            for (int x = 0; x &lt; msgCount; x++)&lt;br /&gt;            {&lt;br /&gt;                OpenPOP.MIMEParser.Message msg = client.GetMessage(x, false);&lt;br /&gt;                if (msg != null) {&lt;br /&gt;                    for (int y = 0; y &lt; msg.AttachmentCount; y++)&lt;br /&gt;                    {&lt;br /&gt;                        Attachment attachment = (Attachment)msg.Attachments[y];&lt;br /&gt;                        if (string.Compare(attachment.ContentType, "text/xml") == 0)&lt;br /&gt;                        {&lt;br /&gt;                            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();&lt;br /&gt;&lt;br /&gt;                            string xml = attachment.DecodeAsText();&lt;br /&gt;                            doc.LoadXml(xml);&lt;br /&gt;                            doc.Save(@"C:\POP3Temp\test.xml");&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;That URL again - &lt;a href="http://sourceforge.net/projects/hpop/"&gt;http://sourceforge.net/projects/hpop/&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-4995328275949799584?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/4995328275949799584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=4995328275949799584' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/4995328275949799584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/4995328275949799584'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2008/04/fetching-and-processing-pop3-email-in.html' title='Fetching and processing POP3 email in C#.NET'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-9170441726047690980</id><published>2007-11-30T08:23:00.001Z</published><updated>2011-06-13T16:47:27.347+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='edit'/><category scheme='http://www.blogger.com/atom/ns#' term='div'/><category scheme='http://www.blogger.com/atom/ns#' term='class'/><category scheme='http://www.blogger.com/atom/ns#' term='ammend'/><category scheme='http://www.blogger.com/atom/ns#' term='add'/><category scheme='http://www.blogger.com/atom/ns#' term='attributes'/><title type='text'>Dynamically change the cssclass of a div</title><content type='html'>I can never remember how to do this, so it's definately worth documenting.&lt;br /&gt;&lt;br /&gt;You can add runat="server" and an id tag to any control, and you'll be able to access it from the code-behind, just don't expect to get at all of the &lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;attributes&lt;/span&gt;&lt;/span&gt; that the HTML version presents.&lt;br /&gt;&lt;br /&gt;In my case, you can't edit the CSS class of a div just by adding an id and a runat="server" tag.&lt;br /&gt;&lt;br /&gt;It turns out that you can, but it's not as direct as you may think. Most of the time properties like that come up by default, but not divs! For divs, you have to add the attribute manually:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 204, 0);"&gt;myDiv.attributes("class") = "myclass"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you need to do it for a bind method, you can cast the control to a htmlgenericcontrol.&lt;br /&gt;&lt;br /&gt;All I can is that it's easy when you know how.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-9170441726047690980?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/9170441726047690980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=9170441726047690980' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/9170441726047690980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/9170441726047690980'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/11/dynamically-change-cssclass-of-div.html' title='Dynamically change the cssclass of a div'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-1291158867125429657</id><published>2007-09-27T13:01:00.001+01:00</published><updated>2007-09-27T13:04:47.116+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='event'/><category scheme='http://www.blogger.com/atom/ns#' term='databind'/><category scheme='http://www.blogger.com/atom/ns#' term='datarepeater'/><category scheme='http://www.blogger.com/atom/ns#' term='datasource'/><category scheme='http://www.blogger.com/atom/ns#' term='page_prerender'/><category scheme='http://www.blogger.com/atom/ns#' term='page'/><category scheme='http://www.blogger.com/atom/ns#' term='page_loadcomplete'/><category scheme='http://www.blogger.com/atom/ns#' term='datalist'/><title type='text'>Premature databinding in a user control</title><content type='html'>It happens to us all. You go to bind a data repeater to a user control, but it happens far too soon in the event loading process, and you end up with a repeater that doesn't update until you re-refresh the page.&lt;br /&gt;&lt;br /&gt;An example of this not working is as follows:&lt;br /&gt;&lt;br /&gt;Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load&lt;br /&gt;&lt;br /&gt;            rptBasket.DataSource = bList&lt;br /&gt;            rptBasket.DataBind()&lt;br /&gt;&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;The reason this won't work is because the page_load event happens too soon for your repeater to be bound. So use the page_loadcomplete event, right? Wrong. There is no page_loadcomplete event for user controls, so to get your datalist / datarepeater to bind at the right time, you're going to have to use a page_preRender event. It does the same job as the page_loadcomplete event.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-1291158867125429657?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/1291158867125429657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=1291158867125429657' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/1291158867125429657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/1291158867125429657'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/09/premature-databinding-in-user-control.html' title='Premature databinding in a user control'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-96893805339824650</id><published>2007-09-27T12:39:00.000+01:00</published><updated>2007-09-27T12:41:58.284+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='audioscrobbler'/><category scheme='http://www.blogger.com/atom/ns#' term='creative'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='fm'/><category scheme='http://www.blogger.com/atom/ns#' term='zen'/><category scheme='http://www.blogger.com/atom/ns#' term='stream'/><category scheme='http://www.blogger.com/atom/ns#' term='last'/><title type='text'>Last.FM scrobbling via Creative Zen / Winamp</title><content type='html'>I know this isn't strictly coding-related, but it's a bit geeky for my other blog, and I know for a fact that there are a lot of deserving people out there who want to scrobble Creative Zen Vision:M tracks on their Last.FM account via Winamp.&lt;br /&gt;&lt;br /&gt;The problem is that Winamp grabs the tracks from your player via a http stream which means that audioscrobbler ignores it. The way to get around it is to stop using the latest version of last.fm, and revert to an old version of the audioscrobbler plugin that didn't require the last.fm program.&lt;br /&gt;&lt;br /&gt;The version you're looking for is:&lt;br /&gt;&lt;br /&gt;audioscrobbler.wa.1.1.11.exe&lt;br /&gt;&lt;br /&gt;If you find that, install it instead of your latest plugin, you should be away!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-96893805339824650?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/96893805339824650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=96893805339824650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/96893805339824650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/96893805339824650'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/09/lastfm-scrobbling-via-creative-zen.html' title='Last.FM scrobbling via Creative Zen / Winamp'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-8821358459135953576</id><published>2007-09-06T08:21:00.000+01:00</published><updated>2007-09-06T08:30:05.564+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='hover'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='setattribute'/><category scheme='http://www.blogger.com/atom/ns#' term='states'/><category scheme='http://www.blogger.com/atom/ns#' term='element'/><category scheme='http://www.blogger.com/atom/ns#' term='fundemental'/><category scheme='http://www.blogger.com/atom/ns#' term='lack'/><category scheme='http://www.blogger.com/atom/ns#' term='support'/><category scheme='http://www.blogger.com/atom/ns#' term='problems'/><category scheme='http://www.blogger.com/atom/ns#' term='rollovers'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><category scheme='http://www.blogger.com/atom/ns#' term='strange'/><title type='text'>Element.setAttribute and other strange problems</title><content type='html'>Heed this.&lt;br /&gt;&lt;br /&gt;If you're using javascript events like onmouseover and onmouseout, don't bother using them if you want to do something clever.&lt;br /&gt;&lt;br /&gt;My plan for these events was as follows:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Your image has an onmouseover and onmouseout state. An on / off state.&lt;/li&gt;&lt;li&gt;When clicking this image, the onmouseover and onmouseout state change. So does the source of the image.&lt;/li&gt;&lt;/ul&gt;The trouble with this is that if you want to modify the onmouseover and onmouseout events dynamically in a javascript function depending on whether the image has been clicked or not, you're out of luck. Firefox supports the element.setAttribute('attribute','property') method, but Internet Explorer versions do not.&lt;br /&gt;&lt;br /&gt;Even what Firefox does support seems to be patchy, and doesn't complete my image swapping. The event states didn't want to stick across browser versions.&lt;br /&gt;&lt;br /&gt;It turns out that if you want to alter those mouse-related events, you can't do it dynamically in a javascript function. IE won't let you at all, and Firefox's support seems to be buggy.&lt;br /&gt;&lt;br /&gt;So how did I get around this?&lt;br /&gt;&lt;br /&gt;Our creative girl produced a cascading stylesheet which had images with on/off states in them, and then moved the image depending on what the class of the div surrounding our image was. From there, we could alter the class of the div and therefore alter the hover states.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="link1" class="price_result1"&gt;&lt;br /&gt;    &lt;a href="#" onclick="changeSort(1);" title="Price"&gt;&lt;span class="alt"&gt;Price&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Where price_result1 in the stylesheet is:&lt;br /&gt;&lt;br /&gt;.price_result1 {&lt;br /&gt;    width:44px;&lt;br /&gt;    height:12px;   &lt;br /&gt;    background:url(../images/result_headers/price.gif);&lt;br /&gt;    float:left;       &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;.price_result1 a {&lt;br /&gt;    display:block;&lt;br /&gt;    width:44px;&lt;br /&gt;    height:12px;&lt;br /&gt;    background:url(../images/result_headers/price.gif) 0% 0% no-repeat;&lt;br /&gt;    }&lt;br /&gt;.price_result1 a:hover {background-position:0% 75%;}&lt;br /&gt;&lt;br /&gt;price_result2 is:&lt;br /&gt;&lt;br /&gt;.price_result2 {&lt;br /&gt;    width:44px;&lt;br /&gt;    height:12px;   &lt;br /&gt;    background:url(../images/result_headers/price.gif) 0% 75% no-repeat;&lt;br /&gt;    float:left;       &lt;br /&gt;    }&lt;br /&gt;.price_result2 a {&lt;br /&gt;    display:block;&lt;br /&gt;    width:44px;&lt;br /&gt;    height:12px;&lt;br /&gt;    background:url(../images/result_headers/price.gif) 0% 75% no-repeat;&lt;br /&gt;    }&lt;br /&gt;.price_result2 a:hover {background-position:0% 100%;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And so on.&lt;br /&gt;&lt;br /&gt;I hope this helps. Really I do, because it took me three days to work this out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-8821358459135953576?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/8821358459135953576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=8821358459135953576' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/8821358459135953576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/8821358459135953576'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/09/elementsetattribute-and-other-strange.html' title='Element.setAttribute and other strange problems'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-2564664765800680406</id><published>2007-09-06T08:10:00.000+01:00</published><updated>2007-09-06T08:30:48.172+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='call'/><category scheme='http://www.blogger.com/atom/ns#' term='hidden'/><category scheme='http://www.blogger.com/atom/ns#' term='input'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><category scheme='http://www.blogger.com/atom/ns#' term='field'/><title type='text'>The XMLHttpRequest object</title><content type='html'>This is AJAX related, and likely to cause problems if you're doing what I'm doing.&lt;br /&gt;&lt;br /&gt;I use the object to write out some HTML into a div of a page.&lt;br /&gt;&lt;br /&gt;The HTML I'm writing is from an ASP file, and so the syntax for the (pre-declared object) looks like this:&lt;br /&gt;&lt;br /&gt;   url = "searchDBaseAjax.asp?" + savedUrl;&lt;br /&gt;   url=url+"&amp;sid="+ Math.random();&lt;br /&gt;&lt;br /&gt;   xmlHttp.onreadystatechange=caravanSearchStateChanged;&lt;br /&gt;   xmlHttp.open("GET",url,true);&lt;br /&gt;   xmlHttp.send(null);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now if youre searchDBaseAjax.asp file contains some javascript that you want to write to that div, and you want it to happen straight away, you'll have problems.&lt;br /&gt;&lt;br /&gt;Say you put a hidden input field in your ASP file.&lt;br /&gt;&lt;br /&gt;Say that you then want to test this within the function that you write your ASP file from (just below the code mentioned above).&lt;br /&gt;&lt;br /&gt;           if (document.getElementById('hideHeaders').value == '1') {&lt;br /&gt;               document.getElementById('resultsHeader').className = ' none';&lt;br /&gt;           }&lt;br /&gt;           else {&lt;br /&gt;               document.getElementById('resultsHeader').className = 'floatleft paddingtop15';&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;Because this is an asynchronous call, it's likely that the processing of the AJAX method will not be completed by the time that your javascript underneath executes, and therefore your input field will not be tested properly.&lt;br /&gt;&lt;br /&gt;One solution was to make this method synchronous. (Change the true in the open method to false). Trouble is, that doesn't work.&lt;br /&gt;&lt;br /&gt;So to fix it, I used the xmlHttp.onreadystatechange attribute to specify the method caravanSearchStateChanged which is mentioned in the first code-snippet.&lt;br /&gt;&lt;br /&gt;That method now looks like this:&lt;br /&gt;&lt;br /&gt;function caravanSearchStateChanged()&lt;br /&gt;{&lt;br /&gt;   if (xmlHttp.readyState==4)&lt;br /&gt;   {&lt;br /&gt;           document.getElementById("ajaxSearchResults").innerHTML=xmlHttp.responseText;  &lt;br /&gt;         &lt;br /&gt;           if (document.getElementById('hideHeaders').value == '1') {&lt;br /&gt;               document.getElementById('resultsHeader').className = ' none';&lt;br /&gt;           }&lt;br /&gt;           else {&lt;br /&gt;               document.getElementById('resultsHeader').className = 'floatleft paddingtop15';&lt;br /&gt;           }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;So basically, the ready state for our open method is 4 and I've checked that this is the case before I fire off my new javascript that tests the input field.&lt;br /&gt;&lt;br /&gt;Days of messing about, this took.&lt;br /&gt;&lt;br /&gt;For more information, check out the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms757849.aspx"&gt;MSDN entry&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-2564664765800680406?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/2564664765800680406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=2564664765800680406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/2564664765800680406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/2564664765800680406'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/09/xmlhttprequest-object.html' title='The XMLHttpRequest object'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-2151664459116464393</id><published>2007-06-08T08:48:00.000+01:00</published><updated>2007-08-23T11:53:02.456+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='service'/><category scheme='http://www.blogger.com/atom/ns#' term='indexing'/><category scheme='http://www.blogger.com/atom/ns#' term='query'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><title type='text'>An introduction to indexing</title><content type='html'>I'm writing this blog because there's no solid guide on indexing services with ASP.NET, so I'm going to pull together a bit of a guide on how to do it in the hope it helps someone else.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Setting up&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Setting up the indexing service itself is fairly simple.&lt;br /&gt;&lt;br /&gt;Follow this guide:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.windowsnetworking.com/articles_tutorials/Making-Windows-Server-2003-Indexing-Service-Useful.html"&gt;http://www.windowsnetworking.com/articles_tutorials/Making-Windows-Server-2003-Indexing-Service-Useful.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That guide'll only give you information on creating a query form for ASP.&lt;br /&gt;&lt;br /&gt;To create one with .NET I'll explain some sample code later on.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Indexing PDFs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you're looking to index PDFs as well, download and install this on your server:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.adobe.com/support/downloads/detail.jsp?ftpID=2611"&gt;http://www.adobe.com/support/downloads/detail.jsp?ftpID=2611&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That'll automatically work after you stop and re-start the indexing service. It does take a while so be patient.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;.NET Query Form&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Basic implementation of .NET query forms is explained in the links below:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.codeproject.com/aspnet/search.asp"&gt;http://www.codeproject.com/aspnet/search.asp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;and&lt;br /&gt;&lt;br /&gt;&lt;a href="http://idunno.org/articles/278.aspx"&gt;http://idunno.org/articles/278.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The .NET implementation of a form itself is dead easy. The problem is that most forms would require a search for "Any phrase" and "Exact match" as options.&lt;br /&gt;&lt;br /&gt;The exact match bit is the tricky bit. Code's explained a bit below:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 102, 0);"&gt;'Any Words&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Select DocTitle,Filename,Size,PATH,URL, Rank, Characterization, Write from SCOPE('deep traversal of ""/documents""') where FREETEXT('" &amp; strSearch &amp;amp; "')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 102, 0);"&gt;'Search Exact Phrase&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;strSearch = """" + strSearch + """"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Select DocTitle,Filename,Size,PATH,URL, Rank, Characterization, Write from SCOPE('deep traversal of ""/documents""') where contains('" &amp; strSearch &amp;amp; "')&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The search phrase is double-quoted because the indexing service needs quotes around it to conduct an exact search. That took me quite a while to work out!&lt;br /&gt;&lt;br /&gt;The standard contains statement seems to work for me, although I may come back and correct this if it turns out to not do quite the job I'd expected.&lt;br /&gt;&lt;br /&gt;If anybody has any questions on this, leave a comment with your email address and I'll get back to you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-2151664459116464393?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/2151664459116464393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=2151664459116464393' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/2151664459116464393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/2151664459116464393'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/06/introduction-to-indexing.html' title='An introduction to indexing'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-7268913036077936279</id><published>2007-05-22T16:17:00.002+01:00</published><updated>2011-06-17T09:13:47.239+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='anchor'/><category scheme='http://www.blogger.com/atom/ns#' term='linkbutton'/><category scheme='http://www.blogger.com/atom/ns#' term='tag'/><category scheme='http://www.blogger.com/atom/ns#' term='control'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Opening a new window with a linkbutton control</title><content type='html'>I couldn't do it, and it turns out that lots of other people can't do it either.&lt;br /&gt;&lt;br /&gt;They tried to set the navigateurl attribute to the url they want, and then when they tried to open the link in a new window, they got a load of javascript in the address bar and no link.&lt;br /&gt;&lt;br /&gt;There is a legitimate way around this, but it involves extending the linkbutton, which I didn't have time to do.&lt;br /&gt;&lt;br /&gt;If you do want to do it though, you should try &lt;a href="http://aspnet.4guysfromrolla.com/articles/082405-1.aspx" target="_blank"&gt;the 4guysfromrolla article&lt;/a&gt;, because it does give quite a nice explanation.&lt;br /&gt;&lt;br /&gt;If you want a quick workaround, I suggest that you do the following:&lt;br /&gt;&lt;br /&gt;Swap your linkbutton link with a regular anchor tag.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;a href="#" id="linkTag" runat="server"&amp;gt;This is an example link&amp;lt;/a&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That'll be enough for your aspx page. The runat tag and id tags are new and allow you to get to the control from the code-behind.&lt;br /&gt;&lt;br /&gt;If you're modifiying the control within a datalist or a datarepeater, you'll need to use findcontrol to get hold of it. If you do, you'll need this code:&lt;br /&gt;&lt;br /&gt;Dim link as new htmlAnchor&lt;br /&gt;&lt;br /&gt;link = e.item.findControl("linkTag")&lt;br /&gt;&lt;br /&gt;The above creates a new anchor tag control and finds the one on your page.&lt;br /&gt;&lt;br /&gt;However, if you're just accessing it within a regular function that isn't binding data, you can assign the bits you need like this:&lt;br /&gt;&lt;br /&gt;linkTag.HRef = "http://karlitr0s.blogspot.com"&lt;br /&gt;linkTag.innerText = "Karl's Blog"&lt;br /&gt;linkTag.title = "Karl's Blog"&lt;br /&gt;linkTag.target = "_blank"&lt;br /&gt;&lt;br /&gt;The innertext tag is for labelling your link.&lt;br /&gt;The href tag points to where you need to go.&lt;br /&gt;The target tag is the html equivalent, and opens up the new window for you.&lt;br /&gt;&lt;br /&gt;Doing it this way instead of using Javascript:window.open('') in the href tag means that you don't get your original page from displaying [object] or whatever your browser does when it doesn't understand where it's going within .NET.&lt;br /&gt;&lt;br /&gt;Definately the quickest and easiest way around it, but if you have to use external links a lot in your application or you have to utilise the postback as well, you're probably better off extending the linkbutton.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-7268913036077936279?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/7268913036077936279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=7268913036077936279' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/7268913036077936279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/7268913036077936279'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/05/opening-new-window-with-linkbutton.html' title='Opening a new window with a linkbutton control'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-5243774705384465952</id><published>2007-05-21T17:35:00.000+01:00</published><updated>2007-05-21T17:38:24.248+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='dataset'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='datatable'/><title type='text'>Datasets</title><content type='html'>"One or more rows contain values violating non-null, unique, or foreign-key constraints."&lt;br /&gt;&lt;br /&gt;Very informative error, that. Thanks very much Microsoft.&lt;br /&gt;&lt;br /&gt;This can happen for a number of reasons, but for me it was happening because within the datatable in my dataset, I had columns set with smaller sizes than the actual stored procedure fetched. Therefore, I was trying to fit three litres of water into a two litre bottle.&lt;br /&gt;&lt;br /&gt;I fixed this by matching the data table's column sizes to match those within the database. Somebody else was experiencing similar problems but with a different solution on the &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=364416&amp;amp;SiteID=1"&gt;Microsoft Forums.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-5243774705384465952?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/5243774705384465952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=5243774705384465952' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/5243774705384465952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/5243774705384465952'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/05/datasets.html' title='Datasets'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-8209074254701431876</id><published>2007-05-14T09:30:00.000+01:00</published><updated>2007-05-14T09:33:45.551+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='format'/><category scheme='http://www.blogger.com/atom/ns#' term='cells'/><category scheme='http://www.blogger.com/atom/ns#' term='individual'/><category scheme='http://www.blogger.com/atom/ns#' term='solution'/><category scheme='http://www.blogger.com/atom/ns#' term='gridview'/><title type='text'>Gridview solution</title><content type='html'>I've found the solution to most of my problem!&lt;br /&gt;&lt;br /&gt;The code for a standard gridview is listed below:&lt;br /&gt;&lt;br /&gt;    Protected Sub pubSearchResults_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles pubSearchResults.RowDataBound&lt;br /&gt;        If e.Row.RowType = DataControlRowType.DataRow Then           &lt;br /&gt;            Dim p As New Pub&lt;br /&gt;            p = e.Row.DataItem&lt;br /&gt;            Select Case p.award&lt;br /&gt;                Case 1&lt;br /&gt;                    e.Row.Cells(1).Text = "Platinum"&lt;br /&gt;                Case 2&lt;br /&gt;                    e.Row.Cells(1).Text = "Gold"&lt;br /&gt;                Case 3&lt;br /&gt;                    e.Row.Cells(1).Text = "Silver"&lt;br /&gt;                Case 4&lt;br /&gt;                    e.Row.Cells(1).Text = "Bronze"&lt;br /&gt;            End Select&lt;br /&gt;            Dim lnkEdit As New HyperLink&lt;br /&gt;            lnkEdit = e.Row.FindControl("lnkEdit")&lt;br /&gt;            'lnkEdit.NavigateUrl = "pubSearch_detail.aspx?id=" + p.id&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;The _RowDataBound method is a default gridview method and is called when every row in the grid is created. What I've done is accessed the row's award value (Which was collected from the row) and done a select case on it. From there, I've accessed the row passed in's cell index for the award. It's the second column in on the table, so it's the index 1. I've then assigned the text value Platinum, although I also intend to give it a css class to make it silver, which is just as simple to do.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-8209074254701431876?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/8209074254701431876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=8209074254701431876' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/8209074254701431876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/8209074254701431876'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/05/gridview-solution.html' title='Gridview solution'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-6838087010446893093</id><published>2007-05-11T18:38:00.000+01:00</published><updated>2007-05-11T18:51:07.421+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='data'/><category scheme='http://www.blogger.com/atom/ns#' term='2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='customise'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='styles'/><category scheme='http://www.blogger.com/atom/ns#' term='gridview'/><category scheme='http://www.blogger.com/atom/ns#' term='view'/><category scheme='http://www.blogger.com/atom/ns#' term='asp'/><title type='text'>ASP.NET Web Controls</title><content type='html'>They're not ready yet!&lt;br /&gt;&lt;br /&gt;Its web controls are beginning to cause me problems that I'm not entirely sure how I'm going to find a way around, but I'm going to post it here as soon as I do.&lt;br /&gt;&lt;br /&gt;Imagebuttons do not have an onmouseover / onmouseout feature, which seems ridiculous to me, so I wrote a custom control that takes care of it instead. It inherits the linkbutton control with some additional methods. There are plenty of howtos floating around on the internet, so this wasn't a bit problem for me.&lt;br /&gt;&lt;br /&gt;The big problem is turning out to be the gridview control.&lt;br /&gt;&lt;br /&gt;Sorting out paging and sorting seems like a minimum of fuss, and I'm happy for people that require that really badly, but I'm much more concerned with a lack of &lt;span style="font-weight: bold;"&gt;formatting&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;If you want to add columns to a datagrid in the code-behind, you seem buggered as far as I can see. You can't just do:&lt;br /&gt;&lt;br /&gt;objGrid.columns.add("Column1", datasource.column1)&lt;br /&gt;&lt;br /&gt;Why the hell can't you do that? It's common sense!&lt;br /&gt;&lt;br /&gt;Styling fields is also a problem.&lt;br /&gt;&lt;br /&gt;Say that your database produces a column that will contain an integer from 1 to 5. If you get number 1, you want it to say "Gold" in a nice gold font. If you get number 2, you want it to say "Silver" in nice silver font, and so on.&lt;br /&gt;&lt;br /&gt;How the hell are you supposed to do this? One suggestion was to customise the control by inheriting the grid's class. Why should I have to do this? Why isn't basic styling for the code-behind included? Is this going to happen in .NET 3.0?&lt;br /&gt;&lt;br /&gt;To give you a more accurate picture of what I'm talking about, see the link below:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dabs.com/productlist.aspx?&amp;CategorySelectedId=11146&amp;amp;amp;amp;NavigationKey=11146&amp;PageMode=1"&gt;http://www.dabs.com/productlist.aspx?&amp;amp;CategorySelectedId=11146&amp;amp;NavigationKey=11146&amp;amp;PageMode=1&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Scroll down to the product listing, and you can quite clearly see that those rows of what I reckon is a gridview are customised to style differently depending on their values.&lt;br /&gt;&lt;br /&gt;Some of this was surely done in the code-behind, as an objectdatasource for every page is a bit silly, especially if you want to use a proper data access layer.&lt;br /&gt;&lt;br /&gt;If anybody's got any thoughts on this, feel free to leave a comment and let me know what I'm doing wrong that the gridview supports, as I'm at the end of my tether. How on earth you can see fit to release a control that at best binds with basic styling is ludicrous.&lt;br /&gt;&lt;br /&gt;Furthermore, how the hell is this seen as an enterprise solution if you have to inherit classes and write new methods that do what should happen anyway?&lt;br /&gt;&lt;br /&gt;Rant over, and I'll post a solution with complete explanation as soon as I can.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-6838087010446893093?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/6838087010446893093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=6838087010446893093' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/6838087010446893093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/6838087010446893093'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/05/aspnet.html' title='ASP.NET Web Controls'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4436884927968508267.post-5541032056602829636</id><published>2007-05-11T17:08:00.000+01:00</published><updated>2007-05-11T17:10:07.507+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='introduction'/><title type='text'>An introduction</title><content type='html'>I'm Karl, and I'm starting this blog to vent my frustrations at coding issues in any language I encounter, and to post solutions to problems that have plagued my life since my coding birth. Sounds messy, doesn't it.&lt;br /&gt;&lt;br /&gt;It's about time I started trying to give back to the community since I take so much help from howtos and FAQs.&lt;br /&gt;&lt;br /&gt;All the best,&lt;br /&gt;&lt;br /&gt;Karl.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4436884927968508267-5541032056602829636?l=codingrage.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codingrage.blogspot.com/feeds/5541032056602829636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4436884927968508267&amp;postID=5541032056602829636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/5541032056602829636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4436884927968508267/posts/default/5541032056602829636'/><link rel='alternate' type='text/html' href='http://codingrage.blogspot.com/2007/05/introduction.html' title='An introduction'/><author><name>Karl</name><uri>http://www.blogger.com/profile/09122059398602353617</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://2.bp.blogspot.com/-x-gTa9_SOho/TfeIST1zhLI/AAAAAAAAAIs/V6AGoHTaa6U/s220/me.jpg'/></author><thr:total>0</thr:total></entry></feed>
