navigation
 Thursday, February 04, 2010

Lino Tadros, CEO of Falafel Software, recently participated in an SD Times interview, see the full text here. The interview focuses on the ever increasing pace of software and component evolution, and how component vendors like Telerik and software consultants like Falafel can harness that to bring value to their customers.

posted on February 4, 2010  #    by John Waters  Comments [0]
 Wednesday, January 06, 2010
Two recent events lead me to believe that this may indeed be the case...
posted on January 6, 2010  #    by John Waters  Comments [0]
 Thursday, December 17, 2009

If you, like me, did not install C++, it is not there… see this article. Installing C++ fixed the problem. The C++ team must be getting desperate!

posted on December 17, 2009  #    by John Waters  Comments [0]
 Thursday, December 10, 2009

We are proud to announce that Anneke Leigh has joined Falafel Software as our new Senior Project Manager. Anneke brings many years of successful project management to the table, and will be managing Falafel's rapidly growing Consulting Express business.

posted on December 10, 2009  #    by John Waters  Comments [0]
 Tuesday, November 17, 2009

So the show is on the road again. Falafel has a booth (come visit us), as do all the usual suspects, we met our friends at Telerik, Developer Express etc. The FU T-shirts and Sumo wrestlers are going like hot cake, thanks Matt for making us look good!

The Keynote this morning was a big aha moment from me. Its all about the cloud, which for Microsoft is Windows Azure. Very exciting, they have been busy and come along way since last year. The new SQL Azure service behave just like SQL Server, and you can even use SQL Server Management Studio to work with it using your familiar Transact SQL commands. Also, the development tools, management and monitoring tools, deployment etc are shaping up nicely.

The PDC drop of RIA Services for VS 2010 and .NET Fwk 4/ Entity Fwk 4 is looking very capable, will find out more about that on Thursday.

Now attending a talk on ADO.Net Data Services and .NET Entity Framework. They have done tons of work here since version 2.0. There is model first development (generate the DB from the model), support for POCO classes and change tracking, much better SQL generation and support for executing customized SQL and stored procedures.

Day 2: Wow! Microsoft just released Silverlight 4.0, and it has ALL the features that were missing! I don’t even know where to start! Here is a quick list: supports rich printing, access to external devices, access to webcam and microphone, can run in trusted mode and access file system and cross domain network access, does HTML in OOB mode, full OOB window management support (custom windows chrome), drag and drop files into the SL app, play flash inside the SL app, expanded WCF support (net tcp), right click, improved theming, improved data binding, runs full .net fwk assemblies, twice as fast…. what do you think? Seems like a go? It is beta now and RTM first half of 2010.

Oh – and today Microsoft scored big points by giving all the paying attendees a laptop! That drew some standing ovations at the keynote.

Day 3: Attended “Building Amazing Business Applications with Silverlight 4 and RIA Services” with Brad Abrams, Program Unit Manager. Very slick tooling and designer support! Nice implementation of server and client side filtering, and composing client side operations (filtering, sorting, paging) with server side execution.

I will update this blog as I find out more.

posted on November 17, 2009  #    by John Waters  Comments [0]
 Tuesday, October 13, 2009
Falafel will be exhibiting, come visit our booth to discuss Silverlight for your business, Silverlight Training, or to join our Silverlight team!
posted on October 13, 2009  #    by John Waters  Comments [0]
Lino Tadros is stirring up a huge amount of interest at DevReach 09 in Sofia
 |  |  |  |  |  | 
posted on October 13, 2009  #    by John Waters  Comments [0]
 Wednesday, September 23, 2009

If you are following along in the excellent Walk Through, there is one gotcha.

In the section where you add a custom method to the service, in the current code base you need to add the [Custom] attribute for it to compile:

[Custom] 
public void ApproveSabbatical(Employee current)

Cheers

John

posted on September 23, 2009  #    by John Waters  Comments [0]
 Monday, September 21, 2009

Be sure to tune in to Falafel TV to watch a series of videos on Parallel Computing with Visual Studio 2010 and .NET Framework 4.0. First out, the 101 video shows you how Parallel.For will drastically improve your performance with virtually no new code…

posted on September 21, 2009  #    by John Waters  Comments [0]
 Wednesday, September 16, 2009
Find out how to save time and space (not like Dr Who) by using Differencing Disks to configure variations of your core install in Virtual Machines under Hyper V.
posted on September 16, 2009  #    by John Waters  Comments [1]
 Monday, September 14, 2009

In case you wonder, as I did a few days ago, what Hyper V is, here is a simplified answer (the Wikipedia will tell you more):

Hyper V is kind of like Virtual PC for Servers on Steroids: it allows you to efficiently run and manage a whole bunch of different VMs on one machine. Hyper V is a role that is added to Windows 2008 Server (or Windows 2008 Server R2). Once you add the role, some strange things actually happen to your Windows Server installation: it actually becomes it’s own ‘parent partition’ on the server, so that it is also virtualized along with the VMs that you create.

There are many differences between Hyper V and Microsoft Virtual PC. First of all, the VMs have access to way more virtual hardware: multiple processors (Virtual PC only gives you one processor, even on a many core machine), and much more memory. It also requires Hardware Virtualization Assistance, which is present on most modern manycore processors, but if often turned off in the BIOS (I had to turn it on on my Alienware M17X, see this helpful tip). Hyper V also comes with all kinds of nifty management tools, and is trying to get into the datacenter-level virtualized server market.

To confuse things further, there are lots of different SKUs for Hyper V. You can purchase Microsoft Windows Server 2008 (and R2), and enable the Hyper V role, or you can get the free Microsoft Windows Hyper V Server 2008… it’s almost like SKU palindromes! The latter is a stripped down version of the full server SKU that is just specialized in the Hyper V role, and preconfigured for it.

Why would a developer care about all of this? Well, VMs are a great way to test new software, for instance I will be talking about Visual Studio 2010 and the .NET Parallel Computing initiative, and the current beta happens to not be uninstallable (sorry about the double negations). So if I install it on my machine I have to reinstall everything for the next beta refresh. Having better things to do with my time (like blogging about Hyper V on Sunday evening), I would rather put it in a VM. If you have been paying attention you will recall that MS Virtual PC only supports one processor, so that isn’t going to do me much good testing and demoing Parallel Processing…. hence the Hyper V approach. In a later blog I will detail my whole setup and post more on my findings preparing for the Parallel Processing talk at Silicon Valley Code Camp 09.

posted on September 14, 2009  #    by John Waters  Comments [0]
Today I had an interesting battle getting some Virtual Machines connected to the Internet from within their host operating system, Windows 2008 R2 with Hyper V. Read the article and save yourself some pain...
posted on September 14, 2009  #    by John Waters  Comments [0]
 Thursday, August 27, 2009
Read on to find out where it went and how to get it back…
posted on August 27, 2009  #    by John Waters  Comments [0]
 Friday, May 01, 2009

It seems like Microsoft has teams cranking out frameworks left right and center.. the Common Application Blocks, the MVC Framework, and today I came across Microsoft's new .NET RIA Service Framework.

What does it do? A lot! It provides a complete framework for an n-tier Silverlight application that fetches data from some back end store, binds it to the UI, manipulates it and writes it back.

It is a crafty combination of metadata, naming conventions, code generation and classes that helps you wire up the plumbing and handle tasks like change detection, validation, authorization in a very straight forward manner.

I recommend that you check out the technology if you are about to embark on a n-tier Silverlight application and don't want to write all the plumbing yourself!

posted on May 1, 2009  #    by John Waters  Comments [0]
 Friday, March 27, 2009

This helper will do the trick:

    public static class FileHelper
    {
        public static void MoveWithOverwrite(string sourceFileName, string targetFileName)
        {
            if (File.Exists(targetFileName))
            {
                if ((File.GetAttributes(targetFileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                    File.SetAttributes(targetFileName, FileAttributes.Normal);
                File.Delete(targetFileName);
            }
            File.Move(sourceFileName, targetFileName);
        }
    }

 

 | 
posted on March 27, 2009  #    by John Waters  Comments [5]

Today I was trying to figure out the Linq syntax to find the max DateTime out of a list of objects that had a ModifiedOn property. Here is what I came up with:

DateTime maxLastModified = list.PickListItems.Items.Max(p => p.ModifiedOn);

Too easy, huh?

Actually, this is not so much Linq as just extension methods and lambda expressions, although one could argue that is what Linq is...I will leave that to the philosphers.

 |  | 
posted on March 27, 2009  #    by John Waters  Comments [0]
 Sunday, March 22, 2009
Yesterday, I discovered Mars, and that made my life a whole lot easier! Find out how setting MultipleActiveResultSets in your connection string can solve thorny issues with multiple active SqlDataReaders using the same Connection...
posted on March 22, 2009  #    by John Waters  Comments [1]

Yesterday I was debugging some SQL Server transaction logic, and came across the following handy command to see which transactions are running:

SELECT * 
FROM sys.dm_tran_session_transactions
posted on March 22, 2009  #    by John Waters  Comments [0]
 Saturday, March 07, 2009
Falafel is proud to announce that it just renewed its Microsoft Gold Partnership for the sixth year running.
posted on March 7, 2009  #    by John Waters  Comments [0]
 Saturday, January 17, 2009
As of March 1st, Falafel's new headquarters will move to Capitola, California.
posted on January 17, 2009  #    by John Waters  Comments [0]
 Wednesday, December 10, 2008
The Falafel training department has just shipped the official RadControls for ASP.NET AJAX courseware used for training Telerik customers world-wide.
posted on December 10, 2008  #    by John Waters  Comments [1]
 Wednesday, October 01, 2008
I recently discovered that I can actually use most of my favorite C# 3.0 language features even in projects that target .NET Framework 2.0. Read more to see which...
 |  | 
posted on October 1, 2008  #    by John Waters  Comments [1]
 Wednesday, August 27, 2008
I just learned some very interesting things about WPF, Splash screens and Visual Studio 2008 SP1...
posted on August 27, 2008  #    by John Waters  Comments [1]
 Wednesday, July 23, 2008
Lino Tadros, President and CEO of Falafel Software, has been invited to speak at the DevReach conference in Sofia, Bulgaria
 |  |  |  |  |  | 
posted on July 23, 2008  #    by John Waters  Comments [1]
 Tuesday, July 08, 2008
With projects, as with most other things in life, only one thing is certain, and that is change. This blog talks about how to cope with change using tools like Falafel Software's ActiveFocus.
posted on July 8, 2008  #    by John Waters  Comments [1]
 Monday, July 07, 2008

Saw this article, The Myth of the Interchangeable Programmer. It runs along the lines of the famous Mythical Man Month book by Fred Books, this time applied to off shoring.

Bottom line is that you may find that one developer may be doing 60% of the work of the team, or three developers 80%, and the more people you add to the team, the more you slow down the people who are actually getting something done. The author thinks that from his own experience, a team of eight is the max. I agree. (obviously, for huge projects, you need several teams, but he elaborates on that too).

It is funny, because a client just told me our rate for a senior WPF engineer was way out of their range, and they were looking to outsource it off shore...good luck to them! This is difficult, leading edge technology, and the kind of area where one good senior architect can do something in a week that could take a team of less experienced people months to do.

posted on July 7, 2008  #    by John Waters  Comments [1]
 Friday, June 27, 2008
Falafel Software has released its quarterly update of its popular ActiveFocus product management and team collaboration tool. Read more about the latest version.
posted on June 27, 2008  #    by John Waters  Comments [1]
Read all about the tool that is the talk of the industry, what it does and how Falafel created it...
 |  |  |  | 
posted on June 27, 2008  #    by John Waters  Comments [1]
 Thursday, June 26, 2008

More information is to follow, for now see Telerik's announcement at http://blogs.telerik.com/Blogs.aspx

posted on June 26, 2008  #    by John Waters  Comments [0]
 Tuesday, June 17, 2008
What on Earth are SQL Server Hypothetical Indices, where do they come from, and how do you get rid of them?
posted on June 17, 2008  #    by John Waters  Comments [1]
 Thursday, June 12, 2008
Microsoft Corp just announced that Lino Tadros, President and CEO of Falafel Software, has been voted MVP in C# for the fourth year in a row.
posted on June 12, 2008  #    by John Waters  Comments [1]
 Thursday, June 05, 2008
Falafel Software Inc, a Microsoft Gold Certified Partner providing consulting, training, and custom software development for enterprise and small business customers, is proud to announce the release of the Telerik Trainer product. The Telerik Trainer is a state of the art learning tool, leveraging the latest technologies to combine video training with hands on coding. The tool was custom built for Telerik Corporation, as part of their effort to provide the best online support for their award winning RadControls and Reporting product suites.
posted on June 5, 2008  #    by John Waters  Comments [1]
 Monday, May 26, 2008
Read about a cool hack in Visual Studio 2008 SP1 that allows the designer to fall back on a hardcoded master page if it doesn't manage to locate the correct one.
posted on May 26, 2008  #    by John Waters  Comments [0]
 Thursday, May 15, 2008
Read this article for some simple tips about how to check if you are on the right thread, and if not, now to get to the right thread, when updating a visual component in WPF.
 | 
posted on May 15, 2008  #    by John Waters  Comments [0]
 Tuesday, April 29, 2008
I was working on some code today, that was trying to find a string in a list of strings. I came up with a neat way to express it using a lambda expression.
posted on April 29, 2008  #    by John Waters  Comments [1]
 Thursday, April 17, 2008
If you want to set the same value on a whole set of rows, you can use ActiveFocus powerful multi edit feature to save time.
posted on April 17, 2008  #    by John Waters  Comments [0]
 Tuesday, April 15, 2008
Today I refactored some code that has been bugging me for a while, and wanted to share the results. The change resulted in a substantial code reduction and what I felt was a more elegant solution.
 | 
posted on April 15, 2008  #    by John Waters  Comments [2]
 Monday, March 24, 2008
Santa Cruz, CA— Falafel Software , a Microsoft Gold Certified Partner providing consulting, training, and software development for enterprise and small business customers, is proud to announce the renewal of its Microsoft Gold Certified Partner membership for 2008.
posted on March 24, 2008  #    by John Waters  Comments [0]
 Monday, March 10, 2008
Today I learned how to compare text columns in different SQL server databases that use different collations.
posted on March 10, 2008  #    by John Waters  Comments [2]
 Sunday, March 02, 2008
On March 1st, Falafel Software Inc opened a new office in Santa Cruz, California.
posted on March 2, 2008  #    by John Waters  Comments [0]
 Thursday, February 28, 2008
If you need to create a 'sometimes connected' or briefcase model web application, be sure to check out Google Gears...
posted on February 28, 2008  #    by John Waters  Comments [0]
 Friday, February 22, 2008
If you need to quickly go to a specific artifact, and you know it's number, this is what to do...
posted on February 22, 2008  #    by John Waters  Comments [1]
ActiveFocus has a powerful built in Free Text Search capability.
posted on February 22, 2008  #    by John Waters  Comments [1]
In most projects, you will want to subdivide your project into separate phases, steps, milestones, iterations or whatever it is you call them. We will call them Milestones.
posted on February 22, 2008  #    by John Waters  Comments [1]
You can specify how many rows you want to see in your main grids.
posted on February 22, 2008  #    by John Waters  Comments [0]
 Saturday, February 16, 2008
My colleague Steve Trefethen notified me this morning that Windows Vista SP1 was available on MSDN downloads, so I took it for a spin...
posted on February 16, 2008  #    by John Waters  Comments [0]
 Wednesday, February 06, 2008
Turns out be be very straight forward. Read on to find out how..
posted on February 6, 2008  #    by John Waters  Comments [1]
 Saturday, January 26, 2008
Read how to implement the Singleton Design Pattern in C# using Generics
 | 
posted on January 26, 2008  #    by John Waters  Comments [1]
 Saturday, January 19, 2008
One of the things I have come to love about Linq is how you can focus more on declarative programming: focusing on what you want to accomplish rather than how...
posted on January 19, 2008  #    by John Waters  Comments [1]
 Sunday, December 16, 2007
Here is a new language feature that saves a lot of time and eliminates some mindless typing...
posted on December 16, 2007  #    by John Waters  Comments [1]
 Friday, December 14, 2007

I just learnt something new and cool from one of Scott Guthries blogs: the ?? null coalescing operator in C# 2.0. I never noticed it until now, and actually thought it was part of 3.0, until a kind reader corrected me... it's been around ever since the advent of nullable types in C#.

Basically, this operator works like the T-SQL ISNULL or COALESCE function. Read all about it in Scott's blog!

 

posted on December 14, 2007  #    by John Waters  Comments [1]
 Thursday, December 13, 2007

I recently installed the RTM version of Visual Studio 2008 (previously known as Orcas), which comes with C# 3.0 and .NET Framework 3.5. One of the coolest new things is LINQ, more on that in my next blog. The next coolest thing is the new C# 3.0 language support for lambda expressions, see the node  => part below:

 

XmlHelper.Visit(_rootTOCItem.ParentNode, "tocitem", 
  node => _tocItems.Add((XmlElement)node));

Where _tocItems is a List<XmlElement>  stored in the class that is calling this method.

This works because Visit accepts a delegate, and I am passing in an anonymous delegate above using the new syntax. Visit is just something I wrote that iterates over the nodes in an Xml tree. I could have used Link to Xml for that part, but this is a tree of XmlElements returned by an XmlDataProvider, and Linq to Xml operates on XElements.

 

public class XmlHelper
{
  public delegate void NodeVisitor(XmlNode node);
  
  public static void Visit( XmlNode node, string nodeNameFilter, NodeVisitor visitor )
  {
    if ( node.Name==nodeNameFilter)
      (node);
    if (node.HasChildNodes)
      foreach (XmlNode child in node.ChildNodes)
        (child, nodeNameFilter, visitor);
  }
}
posted on December 13, 2007  #    by John Waters  Comments [1]
 Friday, November 30, 2007
Read about how to alter a column in a replicated table without breaking replication.
posted on November 30, 2007  #    by John Waters  Comments [1]
 Wednesday, November 21, 2007
What is a sparse column and when do I need one? This blog will bring you up to speed.
posted on November 21, 2007  #    by John Waters  Comments [3]
 Tuesday, October 02, 2007
I am currently attending the DevReach conference in Sofia, Bulgaria.
 |  |  | 
posted on October 2, 2007  #    by John Waters  Comments [1]
 Friday, September 21, 2007
I often find myself having to upload data in Excel files into temp tables in SQL Server in order to do ad hoc updates or comparisons. Users will commonly submit an Excel file containing data to verify, insert, update or what not. I know there is a way to have SQL Server read data directly form Excel, so finally I got round to trying that out to make these ad hoc tasks easier. Here is how you do it:
posted on September 21, 2007  #    by John Waters  Comments [2]
 Monday, September 17, 2007
Here is an interesting thing I noted the other day. I have an ASP.Net 2.0 application, and in one of the forms, I store the search criteria that you enter on that page in an instance of my ScheduleSearchCriteria class:
posted on September 17, 2007  #    by John Waters  Comments [1]
 Thursday, August 30, 2007
I was debugging some ASP.Net 2.0 code that renders a PDF to the response buffer of a page request, using code like this (byte[] bytes is the PDF file, which was rendered using Microsoft Reporting Services Web Service interface) :
posted on August 30, 2007  #    by John Waters  Comments [2]
 Monday, August 27, 2007
Discover some strange but sadly true limitations of the Virtual PC support for ISB devices...
posted on August 27, 2007  #    by John Waters  Comments [3]
 Thursday, August 16, 2007

I have spent the last few days trying to install Visual Studio 2008 a.k.a. Orcas Beta 2. The download page is here.

The basic idea is that you download a virtual machine that has both the OS (Windows Server 2003) and Orcas preloaded. First, you download a base file called VSCTPBase.exe, which you unpack to get a virtual hard drive. Then, you download 7 RAR files. The first one is self extracting and extracts itself and the rest of them, and then builds a differencing disk which is added to the initial virtual hard drive to create the final virtual drive. At least, that was the theory!

As the whole setup uses a lot of space, and I am almost out of space (as usual) on my laptop, I borrowed a 300 Gb external disk from work to put the VPC on. I downloaded the files mentioned above onto that disk. I then unpacked the base image, and started unpacking the 7 RARS. Well - somewhere in the middle of the third one, I get an error message saying

"Write error in the file OrcasBeta2_VSTS.vhd. Probably the disk is full."

Not! I had about 250 Gb free on the disk. OrcasBeta2_VSTS.vhd is the differencing disk that was being merged from the RARS. So, I scratched my head, googled, couldn't find anyone else with the same problem, tried downloading the file again, rebooted, tried again, sacrificed a goat. No luck.

So I tried searching for the message above as "Write error in the file" and "Probably the disk is full." Now I got lots of hits, this seems to happen a lot to people. Finally, I stumbled across a post saying that there is a file size limit on FAT32 volumes, somewhere around 4Gb.

FAT32? I had forgotten about that evil stuff, along with win.ini, config.sys, thunking, himem, edlin, floppy disks and gorilla.bas! And sure enough, the 300Gb external drive was formatted as FAT32. Duh!

So, a quick command brought my external I: drive out of the bronze age:

convert I:/FS:NTFS 

And now the extraction worked.

Can you believe that? Poor Microsoft trying to get it's developers to beta test their latest and greatest development tools, and you run into FAT32! Talk about a blast from the past. Tonight I will dream nightmares about 640K memory limits and 16 bit operating systems... and the turbo button.

posted on August 16, 2007  #    by John Waters  Comments [1]
 Sunday, August 12, 2007

I was configuring Custom Errors in the web.config of my ASP.Net 2.0 application, and set it up as follows:

<customErrors mode="remoteOnly" defaultRedirect="~/Error.aspx">
  <error statusCode="403" redirect="~/AccessDenied.aspx" />
  <error statusCode="404" redirect="~/Error404.aspx" />
</customErrors>

I had found the syntax on MSDN. To my surprise, the applicationm wouldn't start, it told me there was something wrong with the value of the mode attribute.

So I went back to MSDN and noticed I had looked at the .NET Framework 1.1 documentation. Clicking on the corresponding 2.0 documentation, I found it had changed to initial Caps:

<customErrors mode="RemoteOnly" defaultRedirect="~/Error.aspx">

Duh! I guess my chances of getting this right the first time were remote only...

posted on August 12, 2007  #    by John Waters  Comments [1]
 Tuesday, July 31, 2007

The other day I was trying to figure out why the ItemCommand associated with an ImageButton in a DataGrid had stopped firing and was surprised by why...

Here is the grid in action:

When I clicked on any of the ImageButtons in the grid, the page did post back, but the ItemCommand didn't fire. I experimented with binding the grid at different points in the page lifecycle, but that didn't help. I also tried switching from a DataGrid to a GridView, thinking such a drastic change might get rid of whatever oddity was going on. No such luck.

Finally, I noticed that the grid attribute EnableViewState was false. Originally, this grid had contained some template items with editable content, including text boxes, drop down lists and checkboxes, and ViewState was turned on. But I replaced that functionality with some client side logic using JavaScript and JSON web service calls, so I figured no viewstate was needed any more, and had turned it off. It wasn't until a few weeks later when someone clicked on these image buttons that the problem showed up.

So, long story short, I changed EnableViewState to true, and voila, it started to work again. It beats me why viewstate is needed for a command event to fire when an image is clicked (I could see the image.x and image.y variables in the postback even when it was turned off), somehow the event bubbling from the image click to the containing DataGrid's ItemCommand handler (RowCommand in the GridView) is dependant on viewstate being turned on. If anyone knows why I am all ears!

posted on July 31, 2007  #    by John Waters  Comments [1]
 Monday, July 23, 2007

I am working on a web application, and some of the client side logic uses JavaScript to get an integer value from a text box. A user logged a bug claiming that when he entered a value that had a leading 0, for instance 0556, the result was in his words "a random number".

I looked up the parseInt global function here, and lo and behold! parseInt interprets a leading 0 as denoting that an octal number follows! It also has special processing for 0x (hexadecimal). To prevent this interpretation, you can specify the radix yourself in an overload of parseInt, for instance:

parseInt( tb.value, 10 );

For base (radix) 10. 

That's all I have to say about that!

posted on July 23, 2007  #    by John Waters  Comments [1]
 Sunday, July 15, 2007

A while back I was trying to figure out how to make F1 bring up a custom help window in our web application ActiveFocus. It is easy enough to trap a keypress and open a window showing the help, but to my frustration, after popping up the new window, the built in Internet Explorer help window popped up too!

I tried various variations of cancelling the kepress event, but nothing seems to work. This is for instance how I cancel Ctrl+F (which normally pops up IEs built in Find dialog, but I wanted it to show a custom search dialog instead) :

<script type="text/javascript">

function onKeyDownH(e)
{
  e = window.event;

  var ctrl = (e.ctrlKey) ? true : false;
  if (ctrl == true )
  {
    if ( e.keyCode == 70)
    {
      e.returnValue = false;
      e.keyCode = 0;
      ShowSearchPage();
    }
  }
}

function onloadH(e)
{
  document.onkeydown = onKeyDownH;
  return true;
}

window.onload = onloadH;

</script>

This cancelling approach by the way does work for other keypresses, just not F1, which has some kind of special internal handing. After much head scratching I finally stumbled across this simple solution:

<body onhelp="ShowHelp(); return false;">

Here, ShowHelp does the actual showing of the help window.

Simple, huh? If anyone knows how to make this cross browser compatible I am all ears!

posted on July 15, 2007  #    by John Waters  Comments [1]
 Sunday, July 01, 2007

Last week I needed to add some personalization features to our ActiveFocus application, and it seemed like the built in logic around the Profile class in ASP.Net 2.0 Personalization would do the trick. It's actually pretty neat. First, you "declare" your profile data in web.config, something like this:

<profile enabled="true">
  <providers>
    <clear/>
    <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ActiveFocus"       applicationName="/ActiveFocus"/>
  </providers>
  <properties>
    <group name="Grids">
      <add name="MainGridRows" type="System.Int16" />
      <add name="DetailGridRows" type="System.Int16" />
    </group>
    <add name="LastProject" type="System.Int32" />
  </properties>
</profile>

The Properties portion defines the profile data structure. You can use simple data types like System.Int16, nested types (like the Grids property), and your own data types. You can also declare how these types are to be serialized.

When you add a declaration like this to your project, Visual Studio 2005 generates a class for you that implements this data structure (more on how this actually needs a little help for it to work later!). The class basically wraps the HttpContext.Current.Profile object, which is of type ProfileBase. It adds accessors for the members you declared in the web.config file, and sub objects for nested types.

In runtime, the ProfileBase reads and writes it values to a column in the table aspnet_Profile. Here is what it looks like when an instance of the profile class above is written to that table:

UserId                               PropertyNames                                                          PropertyValuesString

7B07AE10-61A7-4DEE-AFF1-172BB42A5E95 Grids.DetailGridRows:S:0:1:Grids.MainGridRows:S:1:2:LastProject:S:3:1: 8202

The profile is tied to user using the UserID column, and the PropertyNames column determines what offset and length in PropertyValuesString each data item occupies. For instance, MainGridRows starts at offset 1 and is 2 characters (so the value is 20). You can use attributes in web.config to control how the properties are serialized.

In code, to access the profile, you just need to declare a property in your form that casts the Profile object of the current Page (or HttpContext.Current.Profile) to a WebProfile (this is the type name of the auto generated ProfileBase wrapper) :

protected WebProfile Profile
{
  get
  {
    return (WebProfile) this.Profile;
  }
}

Now you can read and write the Profile using this property:

tbRowsPerMainGrid.Text = Profile.Grids.MainGridRows.ToString();
tbRowsPerDetailGrid.Text = Profile.Grids.DetailGridRows.ToString();

Here is how you can save it back:

Profile.Grids.MainGridRows = Int16.Parse( tbRowsPerMainGrid.Text );
Profile.Grids.DetailGridRows = Int16.Parse( tbRowsPerDetailGrid.Text );
Profile.Save();

Pretty cool, huh?

Profile data can be stored for authenticated users, but it can also be stored for anonymous users and "upgraded" to an authenticated user if the anonymous user becomes an authenticated user.

So what is the catch with all this magic?

Well, it turns out that this handy dandy auto generating of wrapper classes is only done for Web Site Projects, not Web Application Projects (WAPs)! This is true even of the latest Visual Studio 2005 SP1. I tried doing this in the ActiveFocus WAP, and the compile failed miserably, there was no WebProfile class to be found. I figured this would be easy to Google, and indeed it was, and it turns out that there is a Visual Studio add in on gotdotnet that adds this capability to WAPs, but to my dismay I saw that the gotdotnet site is "being phased out", and the download is gone!

So I turned to my old colleague and friend Charlie Calvert at Microsoft, and he did some digging. He found this post at andornot.com, which references the original post by Scott Guthrie on scottgu.com, and helpfully provides the vanished download!

I downloaded the software and installed it, and now when I right clicked on the web.config node in the Solution Explorer, there was a menu option saying Generate WebProfile:

And what's more, it actually worked! ActiveFocus is now equipped with a user profile capability! Thanks for the help, all of you guys with helpful blogs above! Hopefully this blog will help you too.

posted on July 1, 2007  #    by John Waters  Comments [1]
 Friday, June 22, 2007

I have an ASP.Net 2.0 form that uses Teleriks RadServiceManager to call a web service in the same application. All was working fine, but when I deployed it to another machine, the web service calls failed. I checked the Event Log and found something like this:

 

Request format is unrecognized for URL unexpectedly ending in '/ArtifactSearch/'. 

 

Googling turned up this helpful article. Apparently, web service calls using HTTP GET and POST are disabled by default on 1.1 installations, and I guess that can linger in machine.config or somewhere, and even though my app was a 2.0 app, it inherited these settings. You can enable the calls by adding this to the <system.web> section of your apps web.config: 

 

<webServices>

  <protocols>

    <add name="HttpGet"/>

    <add name="HttpPost"/>

  </protocols>

</webServices>

 

That did the trick for me!

posted on June 22, 2007  #    by John Waters  Comments [0]
 Thursday, June 21, 2007

Read all about it here. Something that looks very interesting is support for sometimes connected applications...

posted on June 21, 2007  #    by John Waters  Comments [0]
 Wednesday, June 20, 2007

Today I worked on an AJAX application that uses JSON over xmlhttp to provide a quick search feature in our product ActiveFocus. Here you can see it in action: as you type in the searchbox, each time a key is pressed, the search string is sent to the server, a freetext search is done against the database, the results are returned in a JSON array, and then rendered as a HTML table:

Originally, this was hand coded in JavaScript at a very low level, using an ASP.Net 2.0 page on the server side to create and return the JSON object. The task at hand was to convert this to a more high level approach using Teleriks RadServiceManager to call a ASP.Net 2.0 Web Service, which returns a standard .NET type that is automatically converted to a JSON object.

In my Search Web Service, I return an array of SearchResultRows:

public struct SearchResultRow
{
  public int ID;
  public string ArtifactType;
  // ...
}

[WebMethod(EnableSession = true)]
public SearchResultRow[] ArtifactSearch( string searchKey)
{
  //…

This was amazingly straight forward. On the client side, when the callback returns, you can access the array through JSON indexing, something like this:

function CallSearch( searchKey )
{
  Search.ArtifactSearch(
    searchKey,
    SearchServiceCompleteCallback, SearchErrorCallback);
}


function SearchServiceCompleteCallback(ResponseAsJSON, ResponseAsXml, ResponseAsText)
{
  var Results = ResponseAsJSON;
  for( i=0; i < Results.length; i++)
  {
    // …
 

After debugging it in FireFox/FireBug (highly recommended! See article by my colleague Noel), I switched back to Internet Explorer 7.0 to test it there, confident that all was well. At first, the search behaved just like it should. But when I typed a search phrase that narrowed the search down to just one record in the returned array, I suddenly found that the table of results did not get displayed at all. It would display two or more results, but not one!

Intrigued, I switched back to FireBug to debug the mystery. But in FireFox, a one row array worked just fine. I could inspect the value of Results and see the JSON encoding, and verify that it was correct. So, I switched back to IE, this time using the VS 2005 IDE Script Debugger, which is pretty primitive compared to FireBug, but I had no choice.

Now, when I went to inspect Results, I found something very strange. When two or more records were returned, the JSON looked just like the FireFox version:

But when the call only returned one row, the JSON object had a different layout! Instead of a JSON  array of SearhResultRow records, there was an inner object named the same thing as the type of the array elements (SearchResultRow), which contained the field values for that one record!

Go figure!

At this point I had spent way too much time debugging and needed to get the job done, so I just added a check to see if the singleton format was present and handled the two different cases in seprate branches of the if statement, which did the trick.

However, I am curious as to whether this is a bug or not. Clearly, it is the same code running both server side and client side, yet in the two main browser versions, the JSON objects differ for one record arrays.

Let me know if you have any input! If not, maybe at least this blog will save you some debugging time…

posted on June 20, 2007  #    by John Waters  Comments [0]
 Saturday, April 28, 2007

Behind this dropdownlist is some of the coolest code I have written for ages!

 

 

How can that be? Well, I learnt a lot about generics and anonymous delegates in the process… if you want to see some totally geeky code, read on,

Of course, there is a chance that for most of you this is all old hat, in which case you can go back to sleep…it was new to me for sure.

 

Still awake?

 

So, first of all, I had a lot of fun retrieving the data that populates this list.

The data that drives this DropDownList is a list of what I call FeatureGroups (the list has 2 elements, Defects and  Manage Projects), which has a Master Detail relationship to Features (a FeatureGroup contains 0 or more Features). It is in fact a List<AFFeatureGroup>, where each FeatureGroup contains a List<Feature>. Feature references back to its containing FeatureGroup through a FeatureGroupID member.

 

When I go to populate this list of FeatureGroups, I want to do it in one database call, so what I fetch is a flattened out Result Set that contains { FeatureGroup.ID, FeatureGroup.Name, Feature.ID, Feature.Name }.

I then need to iterate through that result set and for each FeatureGroup.ID I find, see if I already have created a FeatureGroup for that ID, if not, create it, then add the Feature to that new or existing feature group.

 

This is a standard pattern, you would have a list of your FeatureGroups in one hand, and be adding to it and searching in it as you go while looping through the flattened result set. Well here is how to spice it up!

 

It turns out that the generic List<T> type has a Find<T>( Predicate<T> match ). The predicate method is a method that takes a Predicate<T> and returns a bool. This method passed in as this parameter is called once on each item in the list, and the first time it returns true, that will be the item returned by Find. And, when invoking Find, you can pass in an anonymous delegate. In other words, you don’t have to pass in a new Predicate<T>( myCompareMethod ), you can just pass in the implementation of myCompareMethod…

This is how it looks:

 

private static List<AFFeatureGroup> GetFeatureGroupsFromFeatures( List<AFFeature> features )
{
  List<AFFeatureGroup> result = new List<AFFeatureGroup>();
  foreach (AFFeature f in features)
  {
    AFFeatureGroup fg = result.Find(
      delegate(AFFeatureGroup featureGroup) { return featureGroup.ID == f.FeatureGroupID; });
    if (fg == null)
    {
      fg = new AFFeatureGroup(f.FeatureGroupID, f.FeatureGroupName);
      result.Add(fg);
    }
    fg.Features.Add(f);
  }
  return result;
}

 

Let me break this down:

 

-          The method receives a List of AFFeatures, this is the flattened out result set containing one Feature in each row with its FeatureGroup as well.

-          The first line, result = new List<…> just creates an empty list of AFFeatureGroups that I will be returning once populated

-          Then,  I loop through all the features that I have fetched

-          In the loop, I call the Find method of List<AFFeatureGroup>, passing  my find implementation. Note two things:

o   a) I declare that the anonymous delegate accepts a AFFeatureGroup, which is mandated by the signature of Predicate<T>, as this code will be called once for each AFFeatureGroup in the list until a match is found

o   b) Inside the implementation curly braces, I can compare the featureGroup.ID of this passed in AFFeatureGroup to the value of f.FeatureGroupID. Think about that some! This is the powerful part! It’s kind of like in Delphi when you could pass in the address of a local nested method and that method would have access to any local variables or parameters in the enclosing method scope. The variable f is in the loop that encloses the call to Find, so in effect, what the compiler does is it captures the current value of f when creating the anonymous method, and makes it available inside the method body! Basically you have a dynamically created nested local method inside of the for loop. This is awesome compiler magic!

-          OK, so if a match is not found, I create a new AFFeatureGroup, and I then add it to the result list

-          If a match was found, or if I just created one, I can now add the feature itself to the feature group

 

And that is it: with this simple set of code I am doing a pretty complex construction of objects! This is what the language features of C# 3.0 will be taking one step further, where I will be able to use type inference to get rid of even more code above, for instance the declaration delegate(AFFeatureGroup featureGroup) can go away and I will just have a lambda expression there instead.

 

So, now for geek part 2…. I now have a method that will take a flattened list and build my two dimensional structure, but now I want to cache that list. Well, first I started with the classic approach, I look in the Cache object for a certain key, and if I don’t find it, I go fetch the data from the database (using the method in part 1), and store it in the cache. But this gets so repetitive, and I also wanted to centralize some of the aspects of the caching, like for how long the cached data is kept.

 

I started off along the lines that my colleague Adam Markowitz pioneered in the Velocity project, where you basically can create a CacheManager class that uses generics to do a type safe cache search. But then I figured if List<T> can accept a Predicate<T> in its Find method, why can’t I write a Cache.Get<T> that also accepts a T Fetcher<T> that will be invoked if there is no cache hit? Of course, Fetcher<T> might need some parameters, so I decided I would need two types of delegate, one that takes no parameters, and one that takes an instance of some arbitrary type D as a parameter (I could have been lazy and used an object instead of D, but what I love about Generics is the type safety it gives you without the performance drawbacks) :

 

public delegate T Fetcher<T, D> ( D data );
public delegate T ParameterlessFetcher<T>();
 

 

Now, my CacheManager can accept one of these 2 delegate types as a parameter in its GetFromCache method, and invoke it if the Cache doesn’t have the sought after data. For instance using the parameterless delegate:

 

public static T GetFromCache<T>(string key, ParameterlessFetcher<T> fetcher)
{
  T res = GetFromCache<T>(key);
  if (res == null)
  {
    res = fetcher();
    AddToCache(key, res);
  }
  return res;
}

 

The GetFromCache and AddToCache are the actual Cachce accessors:

 

public static void AddToCache(string key, object dataToCache)
{
  HttpContext.Current.Cache.Insert(key, dataToCache, null, DateTime.MaxValue, m_defaultTimeSpan);
}

public static T GetFromCache<T>(string key)
{
  return (T) HttpContext.Current.Cache[key];
 

 

Note that I centralize the timespan handling so that this is consistent:

 

private static TimeSpan m_defaultTimeSpan = new TimeSpan(0, 20, 0);

 

Here is how the parameter version looks:

 

public static T GetFromCache<T,D>(string key, Fetcher<T,D> fetcher, D data )
{
  T res = GetFromCache<T>(key);
  if (res == null)
  {
    res = fetcher(data);
    AddToCache(key, res);
  }
  return res;
}

 

And, putting it all together:

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Caching;

namespace Falafel.ActiveFocus.Common
{
 public class AFCacheManager
 {
  private static TimeSpan m_defaultTimeSpan = new TimeSpan(0, 20, 0);

  public delegate T Fetcher<T, D> ( D data );
  public delegate T ParameterlessFetcher<T>();

  public static T GetFromCache<T,D>(string key, Fetcher<T,D> fetcher, D data )
  {
    T res = GetFromCache<T>(key);
    if (res == null)
    {
      res = fetcher(data);
      AddToCache(key, res);
    }
    return res;
  }

  public static T GetFromCache<T>(string key, ParameterlessFetcher<T> fetcher)
  {
    T res = GetFromCache<T>(key);
    if (res == null)
    {
      res = fetcher();
      AddToCache(key, res);
    }
    return res;
  }

  public static void AddToCache(string key, object dataToCache)
  {
    HttpContext.Current.Cache.Insert(key, dataToCache, null, DateTime.MaxValue, m_defaultTimeSpan);
  }

  public static T GetFromCache<T>(string key)
  {
    return (T) HttpContext.Current.Cache[key];
  }
 }
}
 

 

Now, what is exciting here is that I have a completely generic cache manager that can store and retrieve anything in a typesafe manner, using a delegate to do any fetching needed! Here is how I now use it to fetch that cached list of FeatureGroups:

 

public static List<AFFeatureGroup> CacheAllFeatureGroupsAndFeatures()
{
  return AFCacheManager.GetFromCache<List<AFFeatureGroup>>(
    CACHEKEY_FEATUREGROUPS,
    delegate() { return GetFeatureGroupsFromFeatures(new AFFeatureData().GetFeatures()); });
}

 

This is just amazingly concise to me! All I am supplying is :

 

-          the type of the cached object (a List<AFFeatureGroup>)

-          the Cache key to use (the constant CACHEKEY_FEATUREGROUPS)

-          the code to call when missing the data in the cache

 

Note that the code is now another anonymous delegate, it actually calls the method I explained in step 1 above that parses out the flat data. Here you also see how that method in turn gets the data by calling another method, GetFeatures. That in turn actually uses a whole similar approach of generics, that I wrote, which gives as a typesafe  way to convert result sets to lists of objects, but I won’t go there now!

 

And finally, to get down to that dropdownlist:

 

private void PopulateFeatureGroups()
{
  List<AFFeatureGroup> fglist = AFFeatureGroupData.CacheAllFeatureGroupsAndFeatures();
  ddlFeatureGroups.Items.Add(new ListItem("(All)", AFConsts.EMPTY_ITEM_VALUE.ToString()));
  foreach (AFFeatureGroup fg in fglist)
    ddlFeatureGroups.Items.Add(new ListItem(fg.Name, fg.ID.ToString()));
}

And it’s a wrap!

 

And what did I gain from all this convoluted programming asides from elegance and brevity?

I gained a reusable cache that can be tested and trusted and will save me a bunch of time caching other objects in a consistent and type safe manner. Now wasn’t that a geeky way to fill a drop down list?

posted on April 28, 2007  #    by John Waters  Comments [0]
 Tuesday, April 24, 2007
Yesterday I ran into an exception trying to read a non null DateTime value into a nullable type (DateTime?), using a helper method that was calling Convert.ChangeType. It turns out that this method, although very useful, doesn't support nullable types. However, I soon came across a useful blog that has a wrapper class that takes care of that particular problem, courtesy of Peter Johnsson.
posted on April 24, 2007  #    by John Waters  Comments [3]
 Monday, April 09, 2007

I love the new features of ADO.Net, the Object Datasources and the table adapters that the XSD designer can generate. But they kind of have a will of their own! They open and close connections as they see fit, and dont really care about transactions. If you have a set of related tables that you make changes to, and then want to write all of the changes to the database in one transaction, you need to do things a certain way to make it work...

What about the TransactionScope class?

My first attempt was to use the new TransactionScope functionality in ADO.Net 2.0. You can do something like this:

using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
{
   // do stuff that manipulates data
   ts.Complete();
}

While this is a very elegant solution, it is very tricky to get to work. The mechanism uses a Local Transaction Coordinator, but as soon as you execute your second database update command, it escalates the transaction to a distributed transaction (even if you are just doing sequential operations in the same SqlConnection), and tries to do 2 way communication with the DTC (Distributed Transaction Coordinator) running on the SqlServer. This communication turns out to be a major headache to get working. Asides from opening all kinds of firewall holes and configuring lots of complicated DTC options on both the server machine and your local machine, the server needs to be able to do a reverse DNS lookup to call back to your client machine, which proves to be unfeasable if you are developing from home across a VPN or have a dynamic IP address that the server cant lookup. It really only works when your client and the SQL Server are part of the same AD domain.

Long story short, TransactionScope is too complicated right now to actually use in normal development. So I wanted to stick with the traditional transaction support.

Getting the TableAdapters to use the correct Connection object

First of all, you need to make sure all of your TableAdapters use the same Connection object. TableAdapters are not an actual class in ADO.Net, they are code generated classes, kind of like typed DataSets, but unlike typed DataSets they dont inherit from some common TableAdapter class, they just inherit from Component. However, they do expose a Connection property, so I use that to hook up all my TableAdapters to the same Connection object. Something like this:

void InitTableAdapters( SqlConnection conn )
{
  taReportSetGroupAccountNotAssigned.Connection = conn;
  taReportSetGroupAccount.Connection = conn;
  taReportSetGroup.Connection = conn;
  taReportSet.Connection = conn;
}

Setting up the transaction

Now, you can encapsuluate your database operations in a transaction as follows:

SqlConnection conn = new SqlConnection( connStr );

InitTableAdapters( conn );

conn.Open();
SqlTransaction tran = conn.BeginTransaction();
try
{
  // manipulate data

  tran.Commit();
}
catch()
{
  tran.Rollback();
}
finally
{
  conn.Close();
}

However, there is still a problem with this. The SqlCommands inside the TableAdapter need to use the transaction of the Connection object in the Table Adapter, but the generated code does not do that for you. And you don't want to start messing with the generated code, or your changes will be wiped out next time it is regenerated. What to do?

Making the SqlCommand enlist in your transaction

First I tried subclassing the generated TabeAdapter, as I saw there was a protected CommandCollection property. However, it turned out that this collection only contains the Select Command, and I wanted the Insert, Update and Delete commands to participate in the transaction. These are part of the SqlDataAdapter member of the TableAdapter, which is private. Duh!

Well, partial classes come to the rescue! The TableAdapter class is generated as a partial class, which allows you to extend it by adding in additional methods in your own partial class. One gotcha is that you need to use the same namespace for your partial class as for the generated partial class, and that namespace is actually not the same as that of the typed dataset. It has .XXXTableAdapters added on to the end of it, where XXX is the name of your typed dataset. For instance, if your dataset namespace is Falafel.Data, and its name is FalafelDataset, then your TableAdapter namespace will be Falafel.Data.FalafelDatasetTableAdapters.

Armed with this knowledge, we can extend the partial class of each TableAdapter as follows:

namespace Falafel.Data.FalafelDataSetTableAdapters
{
  public partial class ReportSetGroupAccountTableAdapter
  {
    public void JoinTransaction( SqlTransaction tran )
    {  
      TransactionHelper.JoinTransaction(_adapter, tran);
    }
  }
  public partial class ReportSetGroupTableAdapter
  {
    public void JoinTransaction( SqlTransaction tran )
    { 
      TransactionHelper.JoinTransaction(_adapter, tran);
    }
  }
}

Here I am using my own helper class:

public class TransactionHelper
{
  public static void JoinTransaction( SqlAdapter adapter, SqlTransaction tran)
  {
      CheckTransaction(tran, adapter.InsertCommand);
      CheckTransaction(tran, adapter.DeleteCommand);
      CheckTransaction(tran, adapter.UpdateCommand);
      CheckTransaction(tran, adapter.SelectCommand);
  }
  public static void CheckTransaction( SqlAdapter adapter, SqlCommand cmd)
  {
    if (cmd != null)
      cmd.Transaction = tran;
  }
}

Putting it all together

Now that I have injected a public JoinTransaction method into each TableAdapter, I can get them to enlist in the transaction by surreptitiously calling the trojan horse helper:

void EnlistTableAdaptersInTransaction( SqlTransaction tran )
{
  taReportSetGroupAccountNotAssigned.JoinTransaction( tran );
  taReportSetGroupAccount.JoinTransaction( tran );
  taReportSetGroup.JoinTransaction( tran );
  taReportSet.JoinTransaction( tran );   
}

Adding a call to this in my update logic, this is the final sequence of events:

SqlConnection conn = new SqlConnection( connStr );
InitTableAdapters( conn );
conn.Open();
SqlTransaction tran = conn.BeginTransaction();
try
{
  EnlistTableAdaptersInTransaction( tran );
  // manipulate data
  tran.Commit();
}
catch()
{
  tran.Rollback();
}
finally
{
  conn.Close();
}

It's not the most elegant or compact code, but it gets the job done! I hope this will save you some time and allow you to productively use TableAdapters in transactions until the TransactionScope class becomes more development environment friendly!

posted on April 9, 2007  #    by John Waters  Comments [1]
 Tuesday, April 03, 2007

When I first installed Windows Vista I was a little worried that I would not be able to use all my development tools, like Microsoft Visual Studio 2005 and Microsoft SQL Server Management Studio, so I wanted to install an XP virtual machine just in case. I soon found out that the only version of Microsoft Virtual PC that would run on Vista was a beta of Virtual PC 2007, so I installed that, and it actually worked nicely.

Well, now the release version of Virtual PC 2007 is here. You can download the full version for free from the Microsoft Download Center. I downloaded it and installed it (you need to uninstall the beta version first – don’t worry, your virtual machines are left intact).

VPC 2007 runs on most host Windows versions, all the way back to Windows 98. It can of course host Vista, so this is a great way to start testing Vista and application compatibility in a sandbox environment.

posted on April 3, 2007  #    by John Waters  Comments [1]
 Wednesday, March 21, 2007

I am guessing a lot of people out there are like me and have projects that they started working on in ASP.Net 1.1, and later migrated to 2.0. This blog is about how to move your old files into the brave new world...

One of the neat features with web forms created from scratch in 2.0 is the separation of the Code Behind files into two partial classes: one partial class in a file called formname.aspx.designer.cs, and one in formname.aspx.cs. The designer file is autogenerated and contains declarations of all the form level variables, for instance if you drop a TextBox tbMyTextBox onto your form, it will add a line

System.Web.UI.WebControls.TextBox tbMyTextBox

to your designer file.

The other Code Behind file is the one where you write your code, event handlers, etc. The two partial class files are then combined at compile time into one class.

So, how do I take an old 1.1 Code Behind file and separate it into the two files I would have had if I had created it in 2.0? Well, follow these steps:

1. Go to the aspx (same applies for asxc files) file, and change the Page directive to say CodeFile="formname.aspx.cs" instead of Codebehind="formname.aspx.cs"

2. Go to your Code Behind file and delete all the member control declarations that should be in the designer file, for instance the tbMyTextBox in my example (be careful not to delete any other private member variables you may have interspersed with the generated code).

3. Still in the old Code Behind file, add partial in front of the class name of the form, for instance

public partial class formname : System.Web.UI.Page

These three steps are sometimes enough for the IDE to kick in and generate your Code Behind file, but if not, you can prod it on its way a little:

4. Create a file called formname.aspx.designer.cs in the same directory as your formnam.aspx.cs, and copy the basic partial class skeleton structure from your code behind (dont include the : System.Web.UI.Page, and use the same namespace as your partial class):

namespace YourNameSpace {

public partial class formname {

   }
}

5. Add this new file to the project (Project, Add Existing Item). It should line up nicely with your Code Behind file under the aspx node in the Solution Explorer.

6. Go back to the aspx file and change the ID of some arbitrary form level control, then hit Save.... change it back and save again. Now look at your empty stub of a partial class again from step 4...TADA! It now contains declarations for all of your form controls (not just the one you changed!).

By the way, if you for some reason want to declare a member control differently from the way the designer autogenerates it, you can just move it from the generated file back into your file and change for instance the visibility of the variable. The generator checks for existing declarations before it adds them to the generated file (hence step 2 above).

I know this is a tad tedious, I wish there was a wizard, but at least you now know how to make the conversion manually.

posted on March 21, 2007  #    by John Waters  Comments [2]
 Wednesday, March 14, 2007
Today I battled with some interesting problems writing changes to a hierarchical datatable to a SQL Server database. Hopefully by writing about this I can save you some time.
posted on March 14, 2007  #    by John Waters  Comments [1]
 Tuesday, March 06, 2007

There was a bug in SP2 regarding maintenance plans, see official note below:

An issue was recently discovered with SQL Server 2005 SP2 which might impact customers using cleanup tasks in Maintenance Plans and SQL Server Integration Services packages. The issue is described in detail at http://support.microsoft.com/kb/933508. We have created a General Distribution Release (GDR) #50000939 to address this issue which is available for download and we have included the GDR in a refresh of the SP2 installation package

More information can be found here.

posted on March 6, 2007  #    by John Waters  Comments [1]
 Tuesday, February 20, 2007

...and with it a long missed friend returns!

When I first switched from 2000 to 2005, I was dismayed to find that the scripting options were drastically reduced in functionality. I am glad to announce that in SP2, the old 2000 options are all back!

The service pack contains a lot of new functionality, read all about it here. The service pack can be downloaded here.

posted on February 20, 2007  #    by John Waters  Comments [1]
 Tuesday, February 06, 2007

If you use Windows Vista and are like me, you have already turned off those annoying prompts generated by User Account Control (UAC). But can you really just turn it off?

Well, it turns out that you can't. I went to install Adobe Acrobat Reader 8.0, which is Vista compatible. After downloading the file I set about installing it, only to be informed that "The Temp folder is on a drive that is full or is inaccessible."

Some googling turned up this Tech Note on Adobes site. According to this note "On Vista, with User Account Control disabled, there is no write and execute access to the %TEMP% folder". Now isnt that amazing? Microsoft actually turns off access to the TEMP folder if you dont want to use its lousy UAC! I can't believe it!

There are some extremely annoying time consuming work arounds that are detailed in the Tech Note, which entail interrupting the installation half way through, copying files to another location, then running from there... The easist fix is to turn on UAC, reboot (required), run the install, turn off UAC, reboot (required) and there you go!

So thanks Microsoft for adding UAC and then crippling the machine when you turn it off. Very thoughtful.

posted on February 6, 2007  #    by John Waters  Comments [0]
 Monday, January 29, 2007

A couple of days ago I tried to uninstall Telerik's r.a.d.controls 2006 SP3, and the uninstall ran forever before finally failing with an error code. I logged a support ticket and was told that the uninstaller wasn't yet compatible with Vista, but was given a workaround that you might want to know about...

Apparently there is a Microsoft Utility called the Windows Installer Cleanup Utility. You can download it here. It doesn't uninstall programs, but it cleans up their footprint in the installer database and registry. You can then delete the installed files manually and the offending software at least looks like it's gone. Of course, using this brute force method, some things don't get uninstalled, but at least it cleans up somewhat.

If you use this utility, run it before you delete the physical files. It seems that you cant do it the other way round.

posted on January 29, 2007  #    by John Waters  Comments [1]

I have been developing ASP.net Web Applications with Visual Studio 2005 on Windows Vista for a month or so now, and it kind of works. But I have been looking forward to the Visual Studio 2005 SP1, so I was excited to see that Windows Update had tried to install it last night. The install failed, but I set out to figure out what it would take to get it to work on Vista...

The Service Pack can be downloaded manually here. I fetched it and ran it to see what the problem was. It ended up showing me an error box, saying that if I had installed support for Web Application Projects, then I needed to uninstall it before installing the Service Pack, as Web Application Projects are now an integral part of VS 2005 development. I had indeed done that, so I went to the control panel, uninstalled Web Application Projects, and then tried again. Bingo! This time it installed.

Next, I fired up Visual Studio to see if my Web Application Projects would still work. However, I didn't get far - Visual Studio immediately informed me that I needed to get the Visual Studio 2005 Vista SP1. Here is how it is described on the page where you download the regular SP:

"For developers using Visual Studio 2005 on Windows Vista, Microsoft is in current development on an update to Service Pack 1 called the ‘Visual Studio 2005 SP1 Vista Refresh Beta’. This update builds on the improvements made in SP1 and delivers a first class experience for developers wanting to take advantages of the new features in Windows Vista. The Visual Studio 2005 SP1 Update for Windows Vista is expected to ship after the consumer availability of Windows Vista in Q1 of 2007 and is now available in beta."

Wel, I dont have the patience to wait for this to RTM, so I figured I would install the beta. You can get it here.

I went ahead and downloaded the beta. The installation instructions state "On Vista, ensure UAC is turned on". I have turned UAC off, it is the most annoying thing Microsoft created since the Office Paper Clip. But I didnt want to mess up the install, so I turned it back on (which requires a reboot), and then installed the beta (you need to run it as Administrator). That went smoothly, so I turned UAC off again, rebooted, and then started Visual Studio. Cool! No warning messages this time!

Now it was time to see if I could still load my Web Application Projects, so I selected a solution to open and.... it didnt work! Visual Studio told me that I had to install something called "IIS 6 Metabase and IIS 6 Configuration Compatibility". I googled that phrase and ended up on this page. It is a good resource that tells you all the steps needed to run Web Application Projects with IIS (not the built in Development Web Server). One of the steps is to turn on the above mentioned compatibility setting, which you do from the Control Panel, the procedure is well described in the page mentioned above. So, I turned on the compatibilty and tried again!

Lo and behold, this time it worked! As of now, I am back to developing, running and debugging Web Application Projects in Visual Studio against my local IIS, but now with SP1 and the Vista SP1 beta...

posted on January 29, 2007  #    by John Waters  Comments [0]
 Monday, January 22, 2007
Confused as to how you set up synchronization with your PDA in Vista? I was... here is what I found.
posted on January 22, 2007  #    by John Waters  Comments [1]
 Wednesday, January 10, 2007
Find out about a new network protocol from Microsoft that draws neat maps of your network on your Vista machine, and how to make it work play nicely with XP machines on your network…
posted on January 10, 2007  #    by John Waters  Comments [1]