Thursday, July 31, 2008

MyEclipse tabs (views)

If you are new to MyElipse and Elipse you may have accidentally closed one of the tabs in one of your perspectives. I did, and it took me a while to figure out were to go to add it back since I didn't know what the tabs were called anyway. The answer is that they are called Views. Once I figured that out, it was easy to find the solution under Window menu | Show View and then click the View you want to show. You can also use Other... to a full list of Views if you don't see the one you want in the list. You can also drag the View from one dockable area (I don't know what they are really called) to another.

Tuesday, July 29, 2008

Automatically label releases to production using Visual Source Safe

When I move a project from my computer to the production server I like to create a label in Visual Source Safe (VSS) that notes the date and time and that something was deployed. This allows me and others to always know what is in production and how long it has been in production. It also makes it easy to do a bug fix. It is nice to have this at the click of a batch file. Otherwise, I am just to lazy most of the time to wait for VSS (it is on a slow connection so it takes a long time to load or do anything), remember to check in my code, find the project I am working on, then create a label, and type in the date and time and try to remember the format of my label so that is the same. Here is the code I put in a batch file (just create a text file and change the extension to .bat) using my favorite text editor. For more information on how the NOW variable is populated and limitation on it, see my other entry at: http://justgeeks.blogspot.com/2008/07/getting-formatted-date-into-variable-in.html. If you are not using US English data format you will definitely need to change the line that sets NOW to work with your locale. Also, you will need to adjust the paths in this script to match your environment.

@echo off set NOW=%date:~10,4%-%date:~4,2%-%date:~7,2%--%time:~0,2%.%time:~3,2% echo Please make sure all changes are checked in pause set SSDIR=\\myVssServer\someDirWhereIniFileIs"C:\Program Files\Microsoft Visual SourceSafe\ss" Label $/MyVssProjectPath -LDEPLOYED-%NOW% -C- echo A label has been created in VSS called: DEPLOYED-%NOW%

Save output of DOS command to variable

What I want to do is something like: set myVar=pwd BASH and other *nix shells allow you to do things like that (yes the syntax is different) and it is built into the shell. I find it unbelievable that it is so difficult in a batch file to save the output of a DOS command to a variable that can be used later in the script. I know you can use redirection to a file, call the file, delete the file, etc, but that just seems really lame. Then I found that the for loop will allow me to do what I want. It is truly a hack, but it does work, and is fairly straight forward. FOR /F "tokens=1 delims=" %%A in ('pwd') do SET myVar=%%A echo %myVar% if you are not in a batch file you can test it using FOR /F "tokens=1 delims=" %A in ('pwd') do SET myVar=%A echo %myVar%

Getting formatted date into variable in batch file

There are many times I create a batch file to do backups of a deployment before I do a new deployment. I want to keep the history of deployment backups, so I want to include the current date and time in the filename. I could not believe how incredibly different and complex the solutions were for this when I Googled it. I am doing this on my own machine or at least environments that I know so this batch file doesn't have to worry about this working on all machines with different date formats, etc. The script can be adjusted to work on any date format, but it will not work as is on all date formats. As it turns outs there is already a variable with the date and another with time in it called %date% and %time%. You can see this by typing echo %date% %time% at a command prompt. On my machine this returns a string like the following: Tue 07/29/2008 11:30:10.54 A little know bit of functionality built into the command prompt (at least in XP and maybe earlier) is substring functionality. It uses zero based indexes. Using the previous example we can reformat the output to be just about anything we want. As an example lets do 2008-07-29--11.30. To do this we would do the following echo %date:~10,4%-%date:~4,2%-%date:~7,2%--%time:~0,2%.%time:~3,2% Now if you want to use this in a script that zips a directory and gives the filename with the current date and time here is what you could do: set NOW=%date:~10,4%-%date:~4,2%-%date:~7,2%--%time:~0,2%.%time:~3,2% zip -r c:\myApp%NOW%BU.zip \\myserver\myapp

Sunday, July 27, 2008

External Hard Drive setttings

I just found out that buying an external hard drive case that is USB 2.0 and putting an ATA EIDE drive in the case needs to have the correct settings (Single / Master / Slave). I found out that slave sort of works. It worked for about 1 minute before hanging. It also reported some issues when accessing it. I then changed the setting to Single and it works great with no issues. This is the case for Mac OS X and Windows.

Friday, July 25, 2008

A brief overview of Testing

Why do we need to test anyway?
  • Living documentation of the expected behavior of the system
  • To build confidence that software works and still works after making a change
  • Reduce cost by finding bugs early
  • A method to document requirements and verify solution meets the requirements
  • Quality assurance including behavior, performance, etc
Questions to think about?
  • When you make a change, how do you currently determine if the change does what it is supposed to?
  • ... that it didn't break something else?
  • ... where do you document that this is a new requirement?
  • ... how much time will the next programmer have to spend to be able to verify that your requirement still works after his or her new change?
Types of Functional Testing
  • Unit Testing - tests of methods or classes, but not across them.
  • Regression Testing - typically uses unit tests to verify functionality still works as expected
  • System Testing - testing across classes and methods. This is general higher level and tests more of how the system behaves vs the requrements rather than implementation.
  • Integration Testing - tests across classes and methods; it stri
  • Acceptance Testing - done by the end user to give their stamp of approval
Types of Non-Functional Testing Black Box Testing Testing that assumes you don't know the implementation of what is in the box. In this type of testing you have inputs and outputs, but you don't know how inputs are mapped to outputs. In this scenario you think of the box as something you bought or got from someone else, and don't really know how it works, just what it is supposed to do. Examples are: Use case testing, White Box Testing Testing that assumes you DO know the implementation of what is in the box. In fact, the purpose of the test is to make sure that all paths of execution in the box are tested (or at least the ones that can break if you subscribe to Extreme Programming techniques). Typically boundaries, ranges of values, control flow, data flow, and other code execution testing is the focus. Examples are: Unit Testing Test Driven Development Is an approach to design better software. Test Driven Development (TDD) starts the development cycle with gathering requirements, but then quickly moving to writing test cases that document the requirement and force the designer to think about exactly what the system is supposed to do. It takes automated unit testing and regression testing and makes them a basis for all development activities. This means that when adding new functionality a test is written first, it will fail this test at first, then as it is implemented it will eventually pass the test. The best part is now refactoring can take place because we have regression testing already in place to verify by refactoring that we did not break anything. This promotes clean, clear, modularized code because if you can test the code it is likely that it is modular and easier to maintain.

Thursday, July 24, 2008

Adding Loading animation to all AJAX calls

So, you like AJAX, and your users like it except they can't tell when something is being done in AJAX. They complain that there is nothing that indicates to them that something is happening such as a query for a list, save, etc. One solution to this is to show an animated gif next to the element that caused the AJAX call in the first place. While the first line below and the BeginRequest() method are ASP.NET AJAX specific, the addLoadingAnimation() method is just JavaScript and can be used with Java, PHP, etc. The addLoadingAnimation() is IE and FireFox compatible on Windows, and has not been tested in any other browsers or platforms. The animation is removed in the endRequest event in ASP.NET when using an Update Panel. There is nothing needed because of how the Update Panel works. In other situations, the animation may need to be removed manually. Additional code would be needed, but should be able to be done in a similar way. The code assumes that the image for the text input will fit nicely inside the text input. A 16 x 16 image will probably work for text inputs of default height. The loading image for all other elements can be whatever size you like.
// Register our event listener that is called when an AJAX request is made.
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequest);

function BeginRequest(sender, args) {
var srcElement = args.get_postBackElement();
addLoadingAnimation(srcElement);
}

// Adds a loading animated gif to the right of
// the element that started an element
// (Except if the element is a text input,
//  then the image is inside the text input
//  as a background image)
function addLoadingAnimation(srcElement)
{

// if element is a textfield, then show the loading image in the textfield itself.
if (srcElement.tagName == "INPUT" && srcElement.type == "text")
{      
   srcElement.style.backgroundImage = 'url(images/loading.gif)';
   srcElement.style.backgroundRepeat = "no-repeat";
   srcElement.style.backgroundPosition = "right";
}

// else the element looks better with the loading image to the right of the element
else
{
   // only add the animation if it isn't there already
   // i.e. user click link twice in a row
   if (srcElement.nextSibling == null
       ||
       (
           !srcElement.nextSibling.innerHTML
          || (
             srcElement.nextSibling.innerHTML
             && srcElement.nextSibling.innerHTML.indexOf("otherLoadingImage") == -1)
             )
      )
   {
      var anim = document.createElement("span");
      anim.innerHTML = '<IMG ID="otherLoadingImage" BORDER="0" SRC="images/loading.gif">';
      srcElement.parentNode.insertBefore(anim, srcElement.nextSibling);
   }
}
}

Wednesday, July 23, 2008

insertAdjacentElement for FireFox

There is a JavaScript method called insertAdjacentElement() that only works in Internet Explorer (IE) and it is NOT supported in FireFox. There is an alternative however. Here is how you could use insertAdjacentElement() to insert a newly created element to the right of a specified element that already exists on the page: var newElem = document.createElement("span"); newElem.innerHTML = 'this is a new element here'; existingElement.insertAdjacentElement("AfterEnd", newElem); If you are want your code to work in IE and FireFox, try replacing the last line with: srcElement.parentNode.insertBefore(newElem, existingElement.nextSibling); If the browser you are using doesn't support that, you can try replacing the last line with the following (it is the same sometimes, but sometimes not) existingElement.parentNode.appendChild(newElem);

Tuesday, July 22, 2008

Adding a loading animation to your AJAX requests

I think AJAX is great. It can be a little confusing for the user if the response is not immediate though. In cases like these it is nice to give the user some feedback so that they know that something is happening and when it is done. I like to a little spinning wheel or something to indicate this condition. You can easily add this to most requests that are AJAX based with only a few lines of code.

// register the event listeners so we will receive the events 
//when they are fired by the AJAX.NET framework
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequest);

function BeginRequest(sender, args) {
  // srcElement is the object that invoked the AJAX call. For example, maybe a textfield
  var srcElement = args.get_postBackElement();
 
  // the path should point to a nice animated gif.
  srcElement.style.backgroundImage = 'url(images/loading.gif)';
  srcElement.style.backgroundRepeat = "no-repeat";
  srcElement.style.backgroundPosition = "right";
}

You can use what ever image you want for the animation. I like this one from the AJAX toolkit. It is from the DynamicPopulate Demo

Start or Stop MS SQL Server using a shortcut

If you are like me you don't always develop against SQL Server on you local computer. Most of the time I use one of the servers in the office. I never seem to have enough memory, so I don't have the MS SQL Server service launch on startup. This saves memory for other things I am doing. However, when I want to start MS SQL Server, I hate navigating and starting it manually. I figured out that I can start it just by double-clicking a windows shortcut and that is really nice. I don't recommend making a shortcut that points to the sqlserver.exe, instead I recommend creating a shortcut that just starts the windows service. This way it is fully accessible, and works the way it was meant to. Here is what you do.
  1. Create a new shortcut.
  2. When it asks you to browse or specify the location of what you want the shortcut to point to, enter the following: cmd /c net start MSSQLSERVER
  3. Click next, and call the shortcut whatever you want.

Click finish, and that is it. Now you can start MS SQL Server manually, but with the click of an icon. You can stop it the same way, just use the following command: cmd /c net stop MSSQLSERVER

Monday, July 21, 2008

Understand AJAX Client Side Events

I found this example in the AJAX.NET documentation, and it is very helpful for understanding how javascript events work and when they fire. To figure see the events firing on your own AJAX enabled page do the following.
  1. Create a new javascript file in your Visual Studio Web Site.
  2. Copy the javascript code below into a .js file and call it what ever you like. In this example I'll call it AjaxEvents.js.
  3. Add the following line in blue to your script manager that already exists on your page <asp:scriptmanager id="ScriptManager1" runat="server"> <span style="color: rgb(0, 0, 153); font-weight: bold;"> <scripts><asp:scriptreference path="AjaxEvents.js">/asp:scriptreference></scripts> </asp:scriptmanager>
  4. Add the following HTML somewhere on your page. It will be used to append debug text as the events fire. <span id="ClientEvents"></span></span>
Now you can do what ever you usually do to make your AJAX code execute, but this time you will see the JavaScript events that are firing. You can now add cool things to the client side when these events occur. Some ideas are display animations when AJAX is running, progress messages, disabling or enabling page elements. The possibilities are great. Obviously, you will want to remove the debugging code and probably the span tag since all this is just to show you how the events fire and help you understand serves as a starting point where you can put your code that does the more interesting stuff.

// Hook up Application event handlers.
var app = Sys.Application;
app.add_load(ApplicationLoad);
app.add_init(ApplicationInit);
app.add_disposing(ApplicationDisposing);
app.add_unload(ApplicationUnload);


// Application event handlers for component developers.
function ApplicationInit(sender) {
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (!prm.get_isInAsyncPostBack())
{
   prm.add_initializeRequest(InitializeRequest);
   prm.add_beginRequest(BeginRequest);
   prm.add_pageLoading(PageLoading);
   prm.add_pageLoaded(PageLoaded);
   prm.add_endRequest(EndRequest);
}
$get('ClientEvents').innerHTML += "APP:: Application init. <br/>";
}
function ApplicationLoad(sender, args) {
$get('ClientEvents').innerHTML += "APP:: Application load. ";
$get('ClientEvents').innerHTML += "(isPartialLoad = " + args.get_isPartialLoad() + ")<br/>";
}
function ApplicationUnload(sender) {
alert('APP:: Application unload.');
}
function ApplicationDisposing(sender) {
$get('ClientEvents').innerHTML += "APP:: Application disposing. <br/>";

}
// Application event handlers for page developers.
function pageLoad() {
$get('ClientEvents').innerHTML += "PAGE:: Load.<br/>";
}

function pageUnload() {
alert('Page:: Page unload.');
}

// PageRequestManager event handlers.
function InitializeRequest(sender, args) {
$get('ClientEvents').innerHTML += "<hr/>";
$get('ClientEvents').innerHTML += "PRM:: Initializing async request.<br/>";
}
function BeginRequest(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Begin processing async request.<br/>";
}
function PageLoading(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Loading results of async request.<br/>";
var updatedPanels = printArray("PanelsUpdating", args.get_panelsUpdating());
var deletedPanels = printArray("PanelsDeleting", args.get_panelsDeleting());

var message = "-->" + updatedPanels + "<br/>-->" + deletedPanels + "<br/>";

document.getElementById("ClientEvents").innerHTML += message;
}
function PageLoaded(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Finished loading results of async request.<br/>";
var updatedPanels = printArray("PanelsUpdated", args.get_panelsUpdated());
var createdPanels = printArray("PaneslCreated", args.get_panelsCreated());

var message = "-->" + updatedPanels + "<br/>-->" + createdPanels + "<br/>";
  
document.getElementById("ClientEvents").innerHTML += message;
}
function EndRequest(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: End of async request.<br/>";
}

// Helper functions.
function Clear()
{
$get('ClientEvents').innerHTML = "";
}
function printArray(name, arr)
{
 var panels = name + '=' + arr.length;
 if(arr.length > 0)
 {
     panels += "(";
     for(var i = 0; i < arr.length; i++)
     {
         panels += arr[i].id + ',';
     }
     panels = panels.substring(0, panels.length - 1);
     panels += ")";
 }
 return panels;
}

Friday, July 18, 2008

Don't be afraid of Generics in C#

I have been really slow to start using Generics and I have been even slow about writing my own methods that make use of Generics in C# (.NET 2.0 or newer). Today I realized exactly how easy it is to write a very generic method and have it use any type you want it to. This is of course the beauty of Generics. Without rambling anymore about my reluctance, here is how you do it. Let's assume that you are writing a bunch of methods that are all the same except they take different type of objects or even primitives as parameters. Here is a simple example of what you could write for each type you want: public static void AreEqual(int a, int b) { return a.Equals(b); } public static void AreEqual(string a, string b) { return a.Equals(b); } This is trivial example where the logic of the code is VERY simple. Imagine if that was a complex algorithm like searching or sorting. Would you really want to have that logic duplicated for each type that you want to work with. Of course not. Again, the prime reason for using Generics. Here is what you could write using Generics (Write once for ALL types): public static void AreEqual<T>(T a, T b) { return a.Equals(b); } You'll notice it looks very similar to the non-generic code except that it uses T instead of a type that you are used to. T is a special placeholder for what type the calling code wants it to be. Here is how you would call the non-generic code: bool retval = AreEqual(1, 0); bool retval = AreEqual("xxx", "yyy"); Here is how you could call the generic code: bool retval = AreEqual<int>(1,0); bool retval = AreEqual<string>("xxx", "yyy"); The syntax is a little strange at first in the end I find it very easy to use. It helped me to think of it as a runtime search and replace of 'T' with the type I currently want to use.

Can't publish Visual Studio 2005 Web Site because access denied error

If you get an error like "Access to the path 'C:\Documents and Settings\username\Local Settings\Temp\~6d4\bin\App_WebReferences.compiled' is denied." when you use the VS2005 | Build menu | Publish Web Site and your site impersonates a user this may help. Open up Windows Explorer and navigate to the Temp directory specified in the path. In this example, go to "C:\Documents and Settings\usb00528\Local Settings\Temp". Now right-click on the Temp directory and go to the security tab. Add the user that you are impersonating (usually specified in you web.config) and give the user Read and Write permissions. Now re-try the Publish Web Site menu item and it should publish successfully now. Yeah!

Wednesday, July 16, 2008

Check Version of OVSD web-api.jar

When you use the HP OpenView Service Desk (OVSD) web-api.jar to write programs that access the OVSD server you should use the same version that the server is using. The obvious question soon becomes, how do I know what version of the web-api.jar do I have. To determine the version of your web-api.jar do the following: 1. Locate the web-api.jar file you are compiling against in your program. 2. Open a command prompt and cd to the directory that contains your web-api.jar, so that it is your current directory. 3. Now type (or copy and paste) java -classpath web-api.jar com.hp.ifc.sys.AppVersionInfo This should return something like: Acronym: SD Version: 4.5.0588.1706 (SP17) Company: hp OpenView Copyright: Copyright (c) 2004 Hewlett-Packard Development Company, L.P. All Rights Reserved. Description: service desk is a family member of the hp OpenView suite. ProductID: B4321 ProductName: hp OpenView service desk If you don't know what version your server is running the easiest way to tell is to open your client software and look at the start up splash page. If you want a more detailed answer like the above info, you can do the following: 1. Execute C:\Program Files\Hewlett-Packard\OpenView\service desk 4.5\client\bin\sd_version.bat by double clicking it. This should return the same thing as you got for the web-api.jar info.

Tuesday, July 15, 2008

Lookout for Outlook 2007

For those of you that have used Lookout for Outlook 2003 and earlier and have upgraded to Outlook 2007, you have no doubt figured out that Lookout 1.3 does not run or if you are running Lookout 1.2 that it doesn't even load. The reason is that Lookout is looking for a particular COM file that is now the wrong name even though it does actually work with it.

First thing I recommend is downloading the latest release (there will not be anymore because technically MS owns it now and this software is not longer supported by either the original author or MS). One place you can download Lookout 1.3 from is:

http://www.majorgeeks.com/Lookout_d4808.html

To the rescue comes a couple of people. The author says you can just rename the dll it is looking for so that it can find it. That runs the chance of messing up other things if you ask me. However, you can try it if you prefer that solution:

http://www.belshe.com/2007/12/06/how-to-install-lookout-on-outlook-2007/


Another techie figured out the dll that does the dll check and tricked into always being true. Pretty clever. You can download the patched file and replace the one that is installed with Lookout 1.3.

http://www.wirwar.com/blog/2008/01/22/search-e-mail-at-lightspeed-using-lookout-with-outlook-2007/

Apparently there is an issue with dates when .NET Framework 2.0 is installed. Here is a description and fix to the issue.

http://ewbi.blogs.com/develops/2006/04/outlook_lookout.html

You can fix this by checking out the following link on how to patch it Lookout for this issue.

http://www.scw.us/win/FixingLookout/


If you want more background on the issues, etc there is actually a lot of good stuff on the issues at:

http://www.lockergnome.com/windows/2004/07/26/microsoft-lookout-for-outlook/


As you can see Lookout is limited life left in it. Though I imagine clever folks will continue to patch it until a product that is good enough comes along.

Outlook launch error regarding MSOC.DLL

I just upgraded from Outlook 2003 to Outlook 2007. I opened Outlook 2007 and I get a message that says "MAPI was unable to load the information service msoc.dll. Be sure the service is correctly installed and configured." I had to be quick to get it because it oddly disappears and it is not logged to the Windows event log. If you are getting this message it is likely I would say that you are using "Microsoft Office Outlook Connector for IBM Lotus Domino" plug-in for Outlook 2003. When you upgrade to Outlook 2007, the plug-in stays installed. When you open Outlook it tries to connect to the Domino server as it has always, and in Outlook 2007 this plug-in no longer works and appears to not be supported or have a likely shot of being upgraded to work with Outlook 2007. Make sure Outlook 2007 is quit and not hidden process is running (can use Task Manager to check for process called OUTLOOK.EXE). Do yourself a favor, go to Add / Remove Programs and remove "Microsoft Office Outlook Connector for IBM Lotus Domino". It does NOT work in Outlook 2007.This should uninstall the plug-in from Outlook I think. If that doesn't work you can do what I did before I uninstalled it. I just removed the plug-in from Outlook 2007 using Start Menu | Control Panel | Mail and then click the Email Accounts... button. This will take you to a tabbed window. Make sure the E-mail tab is selected. In the list of connections you should see something that indicates the Domino connection (sorry already deleted it so I can't reference the exact text). Highlight it and click the Remove button. Close the Windows and restart Outlook. This is in no way part of the solution, but I wanted to share it anyway. Here is some sample code that I toyed with to attempt to write my own .PST reader, but ended up with the same error when my code ran, and forced me to figure out what the real problem was (see above of course).
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;

public partial class Form1 : Form
{
 public Form1()
 {
  InitializeComponent();
 }

 private void Form1_Load(object sender, EventArgs e)
 {
  Outlook.Application app = new Outlook.ApplicationClass();
  Outlook.NameSpace NS = app.GetNamespace("MAPI");
  Outlook.MAPIFolder objFolder = 
     NS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
  Outlook.MailItem objMail;

  Outlook.Items oItems;
  oItems = objFolder.Items;

  try
  {
   for (int i = 1; i < objFolder.Items.Count; i++)
   {
    objMail = (Outlook.MailItem)oItems[i];
    MessageBox.Show(objMail.Body.ToString());
   }
  }
  catch (COMException ex)
  {
   MessageBox.Show(ex.Message);
  }
  finally
  {
   NS.Logoff();
   objFolder = null;
   objMail = null;
   app = null;
  }
 }
}  


Monday, July 14, 2008

Unlocking Windows Desktop Search

If you have Windows Desktop Search installed by your corporate IT or the like, they may have locked it so that you can't tell Windows Desktop Search where (file system paths) and what (file extensions) to index. Thanks to one of my sys admin friends (I won't name any names in case he wasn't supposed to tell me this) I can now tell Windows Desktop Search to search where and what I want it to, and thus make it a little more useful.

The restriction is created using a group policy. The group policy can be removed by deleting two keys from the registry found at:

HKLM\Software\Policies\Microsoft\Windows\Windows Search

This should make the group policy for these items to not configured. You should also be able to just set the values to 0 to have a similar effect.

In case you need to restore, or just want to know what you are deleting a head of time, here is an export of the registry entries prior to the change.

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Windows Search]
"PreventUsingAdvancedIndexingOptions"=dword:00000001
"PreventModifyingIndexedLocations"=dword:00000001

Format GridView column header text automatically

Here is a snippet of code that I use for with GridViews to convert Database column names to User friendly text. This comes in handy when I am too lazy or not enough time to go through and change the names of the automatically generated column names that are shown as the column headers in a GridView. This also makes it easy to keep the text looking nice even when the columns change and the columns get regenerated. I realize there are some downsides, like slight performance hit, etc, but for departmental solutions were development time is the most precious thing I have, this is a time saver.

This method assumes that your column names are in Pascal Case. This means that all columns start with a capital letter, and that each word in the column name starts with a capital as well. Everything else in between should be lowercase. An example of this is FirstName or LastName or or ZipCode or DisplayName.

// assumes that source text is in PascalCase and that it
// should be changed to more human readable capitalization.
// i.e. BrentVermilion is in pascal case and a more human
// readable form is Brent Vermilion
public static string MakeUserFriendly(string text)
{
 StringBuilder sb = new StringBuilder(text);
 int insertAdjustment=0;
 char ch;
 for (int i = 0; i < text.Length; i++ )
 {
  // AND the previous letter wasn't an Uppercase letter
  if (!char.IsUpper(text[i - 1]))
  {
   // insert a space before the uppercase letter
   sb.Insert(i + insertAdjustment, ' ');
   // we need to keep track of how many space we have added
   // so we know what the adjusted index to insert at will be
   insertAdjustment++;
  }
 }
 return sb.ToString();
}

One place you can call this method is in the PageLoad event.

protected void Page_Load(object sender, EventArgs e)
{
 if (!Page.IsPostBack)
 {
  // convert cryptic Pascal Case header column text
  // (what the user sees) to User friendly readable text
  for (int i = 0; i < myGridView.Columns.Count; i++)
  {
   myGridView.Columns[i].HeaderText =
    MakeUserFriendly(myGridView.Columns[i].HeaderText);
  }
 } 
}

Wednesday, July 9, 2008

ASP.NET Session Timeouts

In ASP.NET there are lots of timeouts. In this blog entry I will be covering in great detail Session timeout due to the complexity of the issue and the fact that I can never remember where all the setting are and what they are for. I am not covering other timeouts except Script Timeout.

SIDE NOTE: Web services that you consume have timeouts before ASP.NET stops waiting for a response from a web service, but I am not covering that here. The web services on the server side have timeouts that are independent of the ASP.NET consuming the web service. I am also not covering timeouts associated with database connections or authentication either. It is however important that all these timeouts be be compatible with each other, otherwise you will get undesirable behavior. For example, don't set your execution time to less than the database timeout. Or don't set the application recycle to be less than the session timeout.


SessionState Timeout
This is the number of minutes before an ASP.NET user session is terminated. It must be an integer, and it is in minutes. The default is to terminate the session after 20 minutes and the application will throw an exception when accessing an terminated session. Another way to think of this is that it is the time between requests for a given session (which is per user) before a session is terminated.

I recommend reading Idle Timeout section below to see how these are related.


Using Web.config
<system.web>
<sessionState timeout="20" />
<system.web>


Using IIS
You can get to the setting by: Open IIS | Properties on Web Site | ASP.NET tab | Edit Configuration... (or Edit Global Configuration to change for more than one site) | State Management tab.

Here you will see a textfield with a label that says "Session timeout (minutes) with a default value of 20 minutes.

Session Timeout Event
When the session times out it fires an event called: Session_End and then when the user hits the page again (after it has expired or the first time), it will start a new session and the Session_Start event is called. It is important to know that the only thing you can really do in the Session_End event is do clean up. This is because this event fire even if a user doesn't hit a page again. In other words, if a session times out due to inactivity, the Session_End is fired even if the user never refreshes the page, etc. It is independent of the page lifecycle. These events are defined in the Global.asax file.


Detecting when a session has timed out
The short answer to this is that you have a session time when the following conditions are met:
Context.Session != null
AND Context.Session.IsNewSession == true
AND Page.Request.Headers["Cookie"] != null
AND Page.Request.Header["Cookie"].indexOf("ASP.NET_SessionId") >= 0

The long answer is read this blog for more details and sample code: http://www.eggheadcafe.com/articles/20051228.asp

and http://aspalliance.com/520


Idle Timeout


IIS 6.0 (and probably 7) has a setting that controls how idle processes are handled.

This can also affect the session timeout indirectly. This is the case when let's say you have the Idle timeout set to 10 minutes to save resources. If your site is not used a lot and say that the only user using your site stopped using it 10 minutes ago, this means that your application will get recycled. One of the side effects of an application getting recycled is that all sessions are terminated also. So, in this case even if your session is set to timeout say in 30 minutes, under some conditions (little traffic), it is effectively 10 minutes.

If you have low traffic on your application I strongly recommend you set the Idle Timeout to at least as long as your session timeout, otherwise you will effectively be limiting the session time to the Idle Timeout when there is very little traffic on your site. This is in my cases not the desired behavior.

Here is what the help docs in IIS say:
"Idle timeout limits helps conserve system resources by terminating unused worker processes by gracefully closing idle processes after a specified idle duration. This allows you to better manage the resources on particular computers when the processing load is heavy, when identified applications consistently fall into an idle state, or when new processing space is not available."


Open IIS | Properties on the App Pool you are using | Performance tab
Here you will see a setting that says: "Shutdown worker processes after being idle for 20 (time in minutes)" where 20 is the default.

NOTE: Some shared hosting provider don't allow you to access or change this value. In this case one option is to at a set interval ping your application (from a program running on another computer) to keep it alive and thus not get recycled. Though some providers may change the setting so that all application are recycled at particular times as well. Best of luck working with shared hosting providers. I would love to have feedback on a shared hosting provider that has settings that are good for low traffic sites.


Recycle Worker Processes
IIS 6.0 (and probably 7) has a another setting that you can set that determines when the worker processes are recycled.

Open IIS | Properties on the App Pool you are using | Recycling tab
Here you will see a setting that says:
"Recycle worker processes (in minutes):" with a default value of 1740 which is 29 hours.

Classic ASP - Session State timeout in IIS
There is a setting in IIS 6 (and probably 5 and 7) that controls the session timeout in minutes if the user does not refresh or change pages in the specified number of minutes. This is for Classic ASP pages NOT ASP.NET. So don't worry about this for ASP.NET. I added it here since it can be confusing You can get to the setting by: Open IIS | Properties on Web Site | Home Directory tab | Configuration button | Options tab.The field label is "Session timeout:" and the value is 20 minutes as the default value.


Classic ASP - Script timeout in IIS
There is a setting in IIS 6 (and probably 5 and 7) that controls the script timeout in seconds. This is the time that ASP allows a script to run before it stops the script and records the event in the Event Log. This is for Classic ASP pages NOT ASP.NET. So don't worry about this for ASP.NET. I added it here since it can be confusing. You can get to the setting by: Open IIS | Properties on Web Site | Home Directory tab | Configuration button | Options tab.The field label is "ASP script timeout:" and the value is 90 seconds as the default value.


Alternate Timeout handling Mechanisms
In some cases you want to inform the user about session timeout status or automatically have it renew, or maybe any other sort of action. You can use JavaScript / AJAX to accomplish this. If you have access to IIS configuration and you are something like an Intranet you can set your application pool to not recycle if you have enough resources, and set an extremely long session timeout and then handle the timeout on the client side instead. This appears to be a much better experience for the user in general. However, you can also use these techniques to just improve the experience the user has when a session times out.

This article goes into great detail so I won't. The article (
http://ajaxpatterns.org/Timeout) does such a wonder job of explaining it. It is complete with demos as well.

Here is a nice link (http://www.pascarello.com/AjaxSessionTimer.aspx) to a timeout warning message box that shows when your session is about to expire. It does not get past the issue of the application being recycled so be sure to adjust that as recommended above.

Here is a link to stuff to make your UI look really cool: http://script.aculo.us/



Script Timeout
While this is not really session timeout, it could affect it in rare instances so I am mentioning it here for completeness. This is the maximum time an .aspx page can run before timing out. It can be set in two places. Either the web.config (or machine.config for all sites) or via code using Script.ScriptTimeout. If you have debug enabled in web.config then the Server.ScriptTimeout is set to 30000000 seconds (or 347.2 days). Otherwise the default is 90 seconds. This setting is most important if you have long requests that need processing like file uploads, etc. In general the defaults are probably ok.

Using the web.config
This sets the timeout to 3 minutes.
<compilation debug="false"/>
<httpRuntime executionTimeout="180" />

Using code
Server.ScriptTimeout

Using IIS
You can get to the setting by: Open IIS | Properties on Web Site | ASP.NET tab | Edit Configuration... (or Edit Global Configuration to change for more than one site) | Application tab.

Here you will see a textfield with a label that says "Request Execution timeout (seconds):" with a default value of 110 seconds.

IMPORTANT NOTE: Be sure to uncheck the "Enable debugging" checkbox next to this field, otherwise, the value will be ignored and set to the 30,000,000 seconds that debugging defaults to.










Wednesday, July 2, 2008

Use Google Page Creator to store files for blogger

I must say I think Google does a nice job on most of their interfaces. They remind me of Apple in that regard. I like blogger, though I think it needs some help when pasting text that is code or xml, I have figured out how to work with that for the most part. You can even up upload pictures for use in your blog. This is pretty cool. I want to be able to upload files like source code files or zip files so others can easily download them instead of copying my partially formatted source code displayed through the browser. I noticed Google offers Google Page Creator (see http://pages.google.com for more info). It is a nice graphical end user tool for creating simple web sites. They give you 100MB of space for FREE. They also give you the ability to quickly and easily upload files to your web space you click the Link button in their tool bar. I then upload my source code I want to share using this window. Then I let it put the link to it on the page. When I look at the link of the page it created for me, I see that I now have a nice public url that I can use as a link in my blogger.com blog (or anywhere else for that matter). Pretty nice for FREE! One last note, you can also upload using the Uploaded stuff widget on the right side of the site manager page. This is basically a little file manager that lets you upload and delete the files as well as show you the size of each file.

Thread safety in C# and ASP.NET

When I started ASP.NET and web programming I thought that I was shielded from race conditions that I learned about in college. Wrong! I found out the hard way after trying to track down an intermittent bug that it is a very real problem even in web programming and that includes ASP.NET. This becomes an issue when you use static variables or methods sometimes. Most of the time I have not found there to be issues with race conditions. However, sometimes there is. This is not the only time it is an issue though. Beware.

I found that it can be difficult to consistently reproduce the bug in web code, though I think it can be done. To make things easier, I simulated the web. I created two threads to create the race condition. I didn't use a Threading Pool, but I think this is close enough, and illustrates the point while reliably and consistently reproducing the race condition.

First I guess I should explain a little bit about what a race condition is. Let's assume you have two threads. They could be two web sessions as each connection to the your ASP.NET application is handled by a thread from the thread pool. The issues comes when those two threads try to access any shared resource. Thread-A sets a value for example, has some kind of delay, and while Thread-A is processing / delaying Thead-B comes along and changes the shared resource before Thread-A has a chance to use / retrieve value from the shared resource. Then when Thread-A finally has a chance to access the shared resource without coding for thread-safety, Thread-A will assume it was the only one that had used the shared resource and thus it will get data it was not expecting. It is probably a good idea to always only allow one object access to a shared resource and only allow one calling object at a time actually call the method.

 I think the easiest way to see this is to look at the output of a program I wrote to see what was actually going on.

Thread-A-Starting
Thread-A-Spawned
Thread-A-Entering Critical Section
Thread-A-New
Generated Value is: 1907360620

Set New Value: 1907360620
Thread-A-Waiting.... forcing race condition
Thread-B-Starting
Thread-B-Spawned

Thread-B-Entering Critical Section
Thread-B-New
Generated Value is: 209463673

Set New Value: 209463673
Thread-B-Waiting.... forcing race condition
Get New Value: 209463673
Thread-A-CriticalSection() returns: 209463673 (Important Line *******)
Thread-A-Exiting Critical Section
Get New Value: 209463673
Thread-B-CriticalSection() returns: 209463673 (Important Line *******)
Thread-B-Exiting Critical Section

The important thing to note is that the return value for both threads is the last value that was set, and this is because both threads entered the critical section of code at the same time or near the same time. When this happens, they basically step on each other's feet and you get bad results.

Below is the same output but there is a lock on the critical section of code so that only one thread can enter it at a time.

Thread-A-Starting
Thread-A-Spawned
Thread-A-Entering Critical Section
Thread-A-New Generated Value is: 1483178371
Set New Value: 1483178371
Thread-A-Waiting.... forcing race condition
Thread-B-Starting
Thread-B-Spawned <Press any key to remember>
Get New Value: 1483178371
Thread-A-CriticalSection() returns: 1483178371 (Important Line *******)
Thread-A-Exiting Critical Section
Thread-B-Entering Critical Section
Thread-B-New Generated Value is: 249049990
Set New Value: 249049990
Thread-B-Waiting.... forcing race condition
Get New Value: 249049990
Thread-B-CriticalSection() returns: 249049990 (Important Line *******)
Thread-B-Exiting Critical Section


The important thing to notice is that the values set by each thread are also retrieved by each respective thread. This is what we want to happen. You will also notice that even though the threads start together or close together, they take turns using the shared resource. In fact, one thread uses the shared resource until it is done with it, and while the other thread waits to use it.

In C# there is something called a Monitor class that locks and unlocks shared resources. They have simplified the syntax much in the same way that they have with database connectivity. If you are familiar with the using () block in your code. You know it implicitly handles the closing a connection for example (even if there is an exception). Well, the lock () block does the same thing for the Monitor class. It basically guarantees that the object will be unlocked even if there is an exception. It does NOT handle deadlocks, though you can do so with try-catch-finally and the Monitor class because it has a TryEnter and allows you to specify how long to wait for a lock before giving up (thus breaking a deadlock).

Below is a snippet of how locks work.



private static Object objLock = new Object();

public void CriticalSection()
{
   lock (objLock)
   {
       // use shared resource here
   }
}


Things to note here are that the objLock variable is both static (this extremely important) and it is also private so that no one else can unlock the lock (which would defeat its purpose). You can use different lock variables for locking different parts of your code. The smaller number of lines of code you lock at a time the better your performance will be. So, you may want to create different locks for different methods if they are not accessing the same shared resource.

If you would like a much more in-depth and more technical explanation of the how and why I suggest what I suggest I recommend you check