navigation
 Tuesday, January 09, 2007

I've written and revised a reasonable number of DotNetNuke modules, as well as Falafel's course material for DNN, and I think I can probably create binary Private Assemblies in my sleep.

I was a little unnerved, then, when I was getting something ready for an important customer this morning, and discovered some very weird and different behavior in my test environment than in the development environment. Specifically, I had written a module which collected some extended profile information from Joe User when he was logged in, which I didn't want to collect for the host user or for members of the Administrator group. So I'd upload the new module (logged in as host), then log out and go register a new user name, going immediately to the new module page, where the first thing I needed to do was enter the profile information. Dutifully, I would enter the information and submit it. And nothing would get updated. Yet this worked perfectly in my development environment.

Did I say it didn't get updated? That's not exactly true. I was feeling pretty confused, so when Lino the Wise walkd past my office, I grabbed him and said "Boss, I need some help". He listened patiently as I explained the problem, then turned to my keayboard to demonstrate.

And it worked just like it should. Lino laughed, and said it was because he was standing there that the problem got scared and went away. Then so did Lino. And the problem came right back. After a while longer, I got another coworker to come in. And again I explained the problem. And again, the program performed correctly. These two times, out of perhaps a hundred attempts.

I tried lots of things. Rebooting, of course, and iisreset. Clearing out the temporary files. Creating a fresh virtual site with the same name as the old one, then a new virtual site with a different name. Nothing worked.

I finally noticed (while doing some further testing, with a second user name) that the information from a previously logged in user was being displayed. I had been in the habit of logging in as host, uploading the new module, then logging out and immediately registering a new user. I resorted to brute force: I displayed the current user id on the form. When I'd enter and submit the new user's information, I checked and found that DNN's this.ModuleId function said I was userId=1 (host). Since I was disabling profile update through this particular page for host and administrators, my updates were getting thrown away. Apparently the couple of times it did update were when I was explaining the issue to co-workers - thus taking longer, letting the cache time out (??) and by the time I loaded the offending page, everything behaved properly.

I loaded DNN 4.4.0, and the problem went away. I had been developing and testing in DNN 4.3.5, because this was a custom job and that's what the customer was using. And the heck of it is, they (or actually, their users) will probably not ever encounter the problem because of the way the module will be used, one user at a time from computers all around the country. This particular bug hatched to frustrate only the developer. Too bad I didn't find that out more quickly...

posted on January 9, 2007  #    by Rick Miller  Comments [0]
 Wednesday, December 27, 2006
One way you might want to customize your Sharepoint home page is to add your company logo to an "Image" web part displayed on the page - in fact, the team site template comes with a "site image" preconfigured on the page. You can change the image presented here by putting the page into edit mode, then edit the "Site Logo" web part, and select the logo. It can be any logo, accessible from anywhere, of any recognized graphic type. Very flexible.
 
And then they turn right around and bite you in the butt, because if you have a logo on your local machine, and you want to use it as the site logo, how the heck do you load it up onto the server? I poked around for a while looking for something that would let me transfer a file up to the server and specify where I wanted it to end up, but had to finally connect to the server by mapping a network drive, and copy the file into the default file location. And oh yeah, you'd better know where the file goes and/or where you placed it, because when you click on the button with the ellipses (...), don't think you're going to find a file open dialog - nope. All you get is a bigger text box into which you can type the logo's path.
 
Our company logo is a JPG file about 450 kb in size, and in its natural state, the image is something like 2109 x 1398 pixels. Too big to fit onto a normal screen, much less squeeze down into a reasonable-sized corner of the screen like you might want for a company logo on a home page. So - when you put in the path to the JPG, there are two possibilities for resizing the logo, both of which sound promising. The options presented for the question "Should the WebPart have a fixed height" are "Yes" (with an option for entering the size in pixels, picas, points, inches, etc), and the second is "No. Adjust height to fit zone". There are corresponding entries for the width. If you pick yes, and enter a reasonable size in pixels (120 x 80), what you get is a logo-sized area with scrollbars which permit you to scroll across the entire 2109 x 1398 pixels. Not very useful. OK, let's choose "No", and let the image be adjusted to fit the zone. Or not - all this choice does is adjust the zone size to fit the image. In other words, the "Site Logo" web part becomes huge, so instead of getting a shrunken logo displayed in a reasonable-sized area, the area baloons up, the logo is displayed full size, and you can now scroll the entire web page using the sdcroll bars on the browser if you want to see the whole thing.
 
Aargh. All I found to do was to edit and re-save the JPG as a smaller size, then use that logo.
posted on December 27, 2006  #    by Rick Miller  Comments [1]
 Tuesday, December 05, 2006

So I recently discovered programming.reddit.com, a site that lists the latest and greatest programming articles and blogs that other people have read and rated, and I noticed a trend: a lot of the articles are about functional programming languages. This piqued my curiosity. After all, what's the big deal? I learned some Scheme in college, and it was weird compared to programming in an imperative style. Besides, functional languages don't even have objects, so they don't have the same power of abstraction, right? (wrong, and wrong again.) Well, since then, I've read several fascinating articles on the advantages of functional programming languages, and this article was one of the best. Then I learned that Microsoft is researching a functional language for .NET, and that many of C# 3.0's features were lifted from it.

So now I'm wondering, will functional programming become the way of the future? I've decided that it's important enough to acquaint myself with functional programming techniques. I surveyed many functional languages, trying to decide which one to choose.

I want to learn F# eventually, but I don't want it to be my first functional language, because it allows a mixture of functional and imperative programming, and while that might be a powerful combination once I'm fluent in both styles, I don't want to be tempted to fall into familiar imperative patterns while I learn this new style of programming.

Clean looks pretty nice; it performed admirably well for a functional language in the Computer Language Shootout, and it even has its own IDE written entirely in Clean! It is a modern language, but its development and usage isn't as widespread as Haskell's, below.

At long last, I come to Haskell. Haskell is a pure functional language, so I won't have the crutch of imperative programming to fall back on. It was designed to be an open standard, consolidating existing functional languages into a common one as a basis for future language design, which also means that it will be an epicenter of new language developments. While the project to create a Haskell IDE written in Haskell is still underway, there is a Haskell plugin for Visual Studio, which is still pre-release, but the author feels that it's getting close.

In the end, I've decided to pursue learning Haskell first, and then probably F#. If I have any great epiphanies, either for or against functional programming, I'll be sure to post my thoughts here.

posted on December 5, 2006  #    by Adam Anderson  Comments [0]
 Thursday, November 16, 2006

This is an interesting article about the performance and scalability of temp table and table variable in SQL Server 2000 and 2005. http://www.lakesidesql.com/articles/?p=12

posted on November 16, 2006  #    by Adam Anderson  Comments [0]
 Tuesday, November 07, 2006

Serializing objects to XML and back again in C# is trivial until you need greater control over the operation.  How do you serialize binary data, Color properties or some object type that hasn't been invented yet?  Implementing IXmlSerializable allows you to read and write object data in whatever format and by any means you choose. 

The example serializes a list of objects with a single Color property. 

<?xml version="1.0" ?>
<Items>
    <Item>Red</Item>
    <Item>White</Item>
    <Item>Blue</Item>
</Items>

The sample below serializes "MyObjects.xml" from disk to populate a MYObjectList object, makes changes to the list and re-writes "MyObjects.xml".  The two important IXmlSerializable methods to override are ReadXml() and WriteXml().  ReadXml() consumes an XmlReader instance.  Here we use a XmlTextReader to pull the xml text off the disk.  Likewise, WriteXml() uses a XmlTextWriter instance to recreate the xml file.
 
class Program
{
  static void Main(string[] args)
  {
    MyObjectList myObjectList = new MyObjectList();

    XmlTextReader reader = new XmlTextReader("MyObjects.xml");
    myObjectList.ReadXml(reader);

    myObjectList.Items.Clear();
    myObjectList.Items.Add(new MyObject(Color.BlanchedAlmond));
    myObjectList.Items.Add(new MyObject(Color.Blue));
    myObjectList.Items.Add(new MyObject(Color.LightSlateGray));

    XmlTextWriter writer = new XmlTextWriter("MyObjects.xml", null);
    writer.Formatting = Formatting.Indented;
    myObjectList.WriteXml(writer);
  }
}
 
<?xml version="1.0" ?>
<Items>
    <Item>BlanchedAlmond</Item>
    <Item>Blue</Item>
    <Item>LightSlateGray</Item>
</Items>
 
The sample is straightforward but you can use the same technique with data of any complexity.  "MyObjectList" contains a List<>, but that fact turns out to be immaterial.  The core idea is that implementing IXMLSerializable ReadXML() and WriteXML() can get the job done no matter what the data is or what format it needs to be saved as.  Here is the full source for the example, followed by an example with a slightly more complex xml structure.

using System;
using System.Collections.Generic;
using System.Text;

using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Drawing;

namespace SerializeGenerics1
{

  public class MyObject
  {
    public MyObject(Color MyColor)
    {
      _myColor = MyColor;
    }

    private Color _myColor;
    public Color MyColor
    {
      get { return _myColor; }
      set { _myColor = value; }
    }
  }

  public class MyObjectList
  {
    List<MyObject> _items = new List<MyObject>();

    public List<MyObject> Items
    {
      get { return _items; }
      set { _items = value; }
    }

#region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()
    {
      return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
      _items.Clear();
      while (!reader.EOF)
      {
        if (reader.ReadToFollowing("Item"))
        _items.Add(new MyObject(Color.FromName(reader.ReadString())));
      }
      reader.Close(); 
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
      writer.WriteStartDocument();

      writer.WriteStartElement("Items");

      foreach (MyObject myObject in _items)
      {
        if (myObject.MyColor.IsKnownColor)
        writer.WriteElementString("Item", myObject.MyColor.Name);
      }

      writer.WriteEndElement(); // close Items tag

      writer.WriteEndDocument();

      writer.Close();
    }

#endregion
}

class Program
{
  static void Main(string[] args)
  {
    MyObjectList myObjectList = new MyObjectList();

    XmlTextReader reader = new XmlTextReader("MyObjects.xml");
    myObjectList.ReadXml(reader);

    myObjectList.Items.Clear();
    myObjectList.Items.Add(new MyObject(Color.BlanchedAlmond));
    myObjectList.Items.Add(new MyObject(Color.Blue));
    myObjectList.Items.Add(new MyObject(Color.LightSlateGray));

    XmlTextWriter writer = new XmlTextWriter("MyObjects.xml", null);
    writer.Formatting = Formatting.Indented;
    myObjectList.WriteXml(writer);
  }
 }
}

This next example serializes settings for a "Wheel of Fortune" style game written in WPF.   The "Color" referenced here is from the Systems.Windows.Media namespace and doesn't have a "Name" property as in the previous example.  The xml file is nested with a Settings/Setting/<properties> structure:

<?xml version="1.0" ?>
<Settings>
  <Setting>
    <Percentage>10</Percentage> 
    <Color>#FFFF0000</Color> 
    <Title>Nice Try</Title> 
    <Description /> 
    <IsWinner>False</IsWinner>
  </Setting>
  <Setting>
    <Percentage>10</Percentage> 
    <Color>#FFB0E0E6</Color> 
    <Title>T Shirt</Title> 
    <Description>T-Shirt</Description> 
    <IsWinner>True</IsWinner> 
  </Setting>
</Settings>

The IXmlSerializable implementation:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.ObjectModel;
using System.Windows.Media;
using System.ComponentModel;
using System.Diagnostics;

namespace Falafel.Training.WPF
{
  public class Settings : IXmlSerializable, IEnumerable
  {
    List<Setting> _items = new List<Setting>();

  public void Add(Setting setting)
  {
    _items.Add(setting);
  }

#region IXmlSerializable Members

  public System.Xml.Schema.XmlSchema GetSchema()
  {
    return null;
  }

  public void ReadXml(System.Xml.XmlReader reader)
  {
    try
    {
      XmlTextReader textReader = reader as XmlTextReader;
      textReader.WhitespaceHandling = WhitespaceHandling.None;

      _items.Clear();

      while (textReader.ReadToFollowing("Setting"))
      {
        Setting setting = new Setting();
        textReader.Read();
        setting.Percentage = Convert.ToInt32(textReader.ReadString());
        textReader.Read();
        setting.Color = (Color)TypeDescriptor.GetConverter(typeof(Color)).ConvertFromString(textReader.ReadString());
        textReader.Read();
        setting.Title = textReader.ReadString();
        textReader.Read();
        setting.Description = textReader.ReadString();
        textReader.Read();
        setting.IsWinner = Convert.ToBoolean(textReader.ReadString());
        _items.Add(setting);
      }
    }
  catch (Exception ex)
  {
    throw new ApplicationException("Unable to open Settings file. " + ex.Message);
  }
  finally
  {
    reader.Close();
  }
}

public void WriteXml(System.Xml.XmlWriter writer)
{
  XmlTextWriter textWriter = writer as XmlTextWriter;
  textWriter.Formatting = Formatting.Indented;
  textWriter.WriteStartDocument();
  textWriter.WriteStartElement("Settings");

  foreach (Setting setting in _items)
  {
    string color = TypeDescriptor.GetConverter(typeof(Color)).ConvertToString(setting.Color);

    textWriter.WriteStartElement("Setting");

    textWriter.WriteElementString("Percentage", setting.Percentage.ToString());
    textWriter.WriteElementString("Color", color);
    textWriter.WriteElementString("Title", setting.Title);
    textWriter.WriteElementString("Description", setting.Description);
    textWriter.WriteElementString("IsWinner", setting.IsWinner.ToString());

    textWriter.WriteEndElement(); // close Setting tag
  }

  textWriter.WriteEndElement(); // close Settings tag
  textWriter.WriteEndDocument();
  textWriter.Close();
}

#endregion

#region IEnumerable Members

  public IEnumerator GetEnumerator()
  {
    return _items.GetEnumerator();
  }

#endregion
 }
}

ReadXML() casts XMLReader to a XMLTextReader to consume the WhiteSpaceHandling property.  Likewise, WriteXML casts XMLWriter to XMLTextWriter to use the Formatting property.   The structure used here of Settings/Setting/<some properties> is entirely arbitrary.  You can read and write to and from any xml structure you care to put together.

 | 
posted on November 7, 2006  #    by Noel Rice  Comments [0]
 Friday, November 03, 2006

Campbell, CA - November 3rd 2006 - Falafel Software is proud to announce that as of November 1, 2006, every member of the Falafel team has achieved MCP status by having passed one or more Microsoft Certification Exams.

"This is a monumental achievement for the Falafel team as I know of no other company with 100% of its team having this level of certification." says Lino Tadros, President of Falafel. "It reflects our commitment to the development community and to the high standards of professionalism and talent we give to our clients."
Go Falafel!

posted on November 3, 2006  #    by Lino Tadros  Comments [0]
 Monday, October 30, 2006

Campbell, CA - October 30th 2006 - Falafel Software today earned the prestigious Microsoft Gold Partner Certification level.

"It is very exciting to all of us at Falafel to achieve this milestone", said Lino Tadros, President & CEO of Falafel Software "We intend to use the new Gold level to create an even stronger relationship with Microsoft for Training and Consulting in the .NET 3.0 based technologies."
Falafel Software is a Gold Certified Partner with ISV Solution Provider and Mobility competencies.

posted on October 30, 2006  #    by Lino Tadros  Comments [0]
 Tuesday, October 17, 2006

In my previous blog, I wrote about how to create generic utility classes that would cast or convert any object to a given type, returning a default if the value was DBNull. I quickly discovered that this code will work just fine as long as the passed type is not nullable. For example, this will work:

int i = ConvertDBNull.To<int>( value, 0 );

But this won't:

int? i = ConvertDBNull.To<int?>( value, null );

The line that fails within the To<>() method is this:

return (T) Convert.ChangeType( value, t );

The reason the call to ChangeType() fails is that there are no conversions defined for the Nullable<> struct, a fact that I find rather puzzling, since it would have been quite easy to do. All you have to do is get the underlying type and convert to it instead. We will still cast the result to the nullable version of the type, because casting a value type to its nullable counterpart is allowed. Here is how to extract that underlying type:

How To Detect Nullable Types Using Reflection

First of all, we will need to be able to detect when a nullable type is passed to the conversion method. The .NET Framework doesn't provide anything that explicitly tests for nullable types, but we can use reflection to determine whether a type is nullable or not. The first thing you need to know is that nullable types are implemented by the framework by using a generic struct called Nullable<>. For example, the following two declarations are identical:

int? i;
Nullable<int> i;

Therefore, if a given type is nullable, it is a generic type whose type is Nullable<>.

private static bool IsNullable( Type t )
{
  if ( !t.IsGenericType ) return false;
  Type g = t.GetGenericTypeDefinition();
  return ( g.Equals( typeof( Nullable<> ) ) );
}

Solving The Conversion Problem

Now that we can detect a nullable type when it's passed, we will need to extract the underlying type. The underlying type is the first and only generic argument passed to the Nullable<> struct. Therefore, the underlying type can be obtained like this:

private static Type UnderlyingTypeOf( Type t )
{
  return t.GetGenericArguments()[ 0 ];
}

We simply need to substitute the underlying type for the nullable type in our original code to get the desired results:

public static T To<T>( object value, T defaultValue )
{
  if ( value == DBNull.Value ) return defaultValue;
  Type t = typeof( T );
  if ( IsNullable( t ) )
    t = UnderlyingTypeOf( t );

  return (T) Convert.ChangeType( value, t );
}

But wait! If you use this method to attempt to convert a null value to a nullable type, the result will be an invalid conversion, because you will be trying to convert null to a value type. We'll have to return without converting if the passed value is null:

public static T To<T>( object value, T defaultValue )
{
  if ( value == DBNull.Value ) return defaultValue;
  Type t = typeof( T );
  if ( IsNullable( t ) )
  {
    if ( value == null ) return default( T );
    t = UnderlyingTypeOf( t );
  }

  return (T) Convert.ChangeType( value, t );
}

Finally, we have a method that will convert any type, including nullable types, to any other type, including nullable types. I hope that you've enjoyed today's submission. If you need training or consulting, contact us and get the Falafel team working for you!

 | 
posted on October 17, 2006  #    by Adam Anderson  Comments [0]