navigation
 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 [0]
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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
ActiveFocus has a powerful built in Free Text Search capability.
posted on February 22, 2008  #    by John Waters  Comments [0]
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 [0]
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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [2]
 Tuesday, October 02, 2007
I am currently attending the DevReach conference in Sofia, Bulgaria.
 |  |  | 
posted on October 2, 2007  #    by John Waters  Comments [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 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 [0]
 Friday, June 22, 2007