Tired of Javascript

by Damon 21. December 2004 06:00

I write a lot of web applications, but I don't like JavaScript. Too many applications made today are forced to be browser applications when the functionality clearly indicates a desktop solution.

There, I said it. I never did much client-server programming so I can't really be accused of holding on to something who's time has come. There are certainly many benefits to web applications too, not the least of which is ease of deployment to the end user. However, after doing several applications that overused javascript in the worst ways (Like implementing a QuickSort that could sort table rows using the DHTML object model) I became very tired of Javascript, with its many idiosyncrisies and fragile nature. I have been accused lately of going too far down this anti-script path. In ASP.NET, its just too easy to set items to auto post back and create the desired effects from within the safe and familiar environment of my favored, garbage collected, strongly typed and compiled language of choice.

To be fair, I view the fact Microsoft has put a great deal of effort into making it easy to deploy WinForms applications via the AppUpdater block and features in VS.NET 2005 as support for my opinions. Web Services + Thick Client + Easy Deployment = Best of many worlds. Even Sun had it figured out several years ago when the came up with Java WebStart: why not run a desktop app via a shortcut to a web site that checks for updated versions of the code it needs to run? Of course, writing desktop apps in Java is less fun than covering yourself with papercuts and jumping into a pool filled with ice-cold lemon juice, so JWS does them little good.

My point in all of this rant was that .NET is wonderfully extensible in many different ways. It was suggested to me that server-side code could be written to generate some basic and common client side Javascript actions, such as making it so that a radio button list could hide or show an ASP:Panel depending on its selection, without postbacks. Seems simple enough, but if designed properly it could be the first step towards bigger and better things.

Without doing any code experimentation yet, I can think of 3 ways I might set out to do this:

Ineritance

Inherit from controls already in .NET to add the functionality desired. For example, create a custom RadioButtonList that is smart enough to generate client side events to perform some action. The problem with this is that I want to leave inheritance as a last result. I may purchase some 3rd party component that I wish to add this functionality to, meaning extending the base controls may not be an option.

Builder

Some type of builder pattern may be appropriate, where the attributes needed to provide the desired run-time functionality are added via logic encapsulated in Builder classes that operate on otherwise vanilla ASP.NET web controls. The downside of this solution is that it seems like it could be a little more dran-n-drop than adding a few lines to your code behinds manually.

Custom Control Library

This idea is intriguing, although probably slightly overengineering a simple problem. We could probably create a library that would allow us to write ASP code such as the following:

<library:ToggleVisibleRunat="server"  ShowValue="Yes" HideValue="No"  Target="loginPanel" Event="IndexChanged" ID="Clientaction1" NAME="Clientaction1">

          <asp:RadioButtonList Runat="server" ID="showLogin" AutoPostBack="False">

                   <asp:ListItem>Yes</asp:ListItem>

                   <asp:ListItem>No</asp:ListItem>

          </asp:RadioButtonList>

</library:ToggleVisible>

<asp:Panel Runat="server" ID="loginPanel">

          ... other stuff here ...

</asp:Panel>

With this type of metaphor, we could also allow dran-n-drop coding, and allow the values such as "ShowVaule" and "Target" to be configured via the Properties Grid and .NET's most excellent design-time support. I will think about this, and come back after some experimentation.

Tags:

Speaking

by Damon 9. December 2004 06:00

What seems like ages ago I spoke at WINETA about Agile Development in the .NET world. When Larry Clarkin made a point of saying that two-time WINETA speakers were a rare-breed indeed I resolved to join that small circle. A while back I had asked the wineta president if I could speak about digital cryptography.

Digital cryptography is near and dear to my heart because its one of the things that got me into .NET. I was writing some client apps that needed to exchange RSA and RC2 key data with some XML web services written in C#. When helping someone debug an issue I sometimes get to the point where I say "Let me drive", meaning I'd like to man the keybaord. I had not gotten down and dirty with an MSFT tool since writing a little OpenGL in Visual C++ 6. Ten minutes with C# and Visual Studio was all it took for me to know this was a better way to go.

At any rate, after this project I did a decent amount of work researching cryptography and learning a little more about the under the hood stuff than you can learn just by looking at API documentation. I now have some experience with algorithms and some of the subtleties of crypto (who knew character encoding would be the #1 things that trip people up?) that comes in handy from time to time, even very recently at work.

At any rate, I intend to cover the the "basics" of a very complex subject:

  • Brief history of crypto
  • Bit twiddling examples
  • Overview of algorithms
  • Overview of algorithm styles (ECB vs CBC vs CBF)
  • ... all with plent of .net code examples
  • WEP key cracker and examples of some crypto attacks, if I have time
Come and see me, if you are so inclined, January 11th, the details are on the WINETA site above.

Tags:

New Blog is almost done

by Damon 9. December 2004 06:00
I wrote some new blog software.
I wanted a more functional dynamic site. It seems to me that 99% of people inclined to keep a software blog are using a pre-packaged solution like DasBlog. A coworker warned me that blog software was non-trivial and could quickly get out of hand. I took this as any self respecting C# developer with an average sized ego would: a clear reason to do it anyway. After stealing a design idea from Open Source Web Design here I am.I'm sure I haven't implemented all the features of something like DasBlog but then again a cute calendar and HTTP_REFERRER tracking aren't big priorities of mine. I have a couple of features I will implement when I get the time though, such as the comments. I'll probably make a couple of posts later about the blog itself, likely the parts that are over-engineered just to try something.

Tags:

I am not famous

by Damon 3. December 2004 06:00

eXtreme Programming book actually printed

I googled my name to see if it had found DamonPayne.com yet and what do I find but a book I worked on so long ago it seems like another lifetime. Behold, a truly ancient book written concerning that "other" single inheritance, garbage-collected, managed programming platform.
I have to admit I actually wasn't happy to see this come out. Its a long story, but in a nutshell I wasn't happy about how the editor handled this project. This incident caused me to stop and ask myself if I should get published in .NET since I vastly prefer it to the "other thing". Right now and for the forseeable future I'm too busy implementing things to write about things, except perhaps for this blog.

Tags:

Sorting Custom Types in code

by Damon 3. December 2004 06:00

Updated (Solution posted)

If you are writing a .NET application you may be tempted to use DataSets to represent relational data in your application. There are any number of good reasons not to use DataSets and even more reasons you may encounter (especially when integrating with systems you cannot control) where DataSets are not an option. An excellent alternative is a Custom Type.
When I implement Custom Types in a system to represent my data I tend to follow a couple of guidlines:
  • Use Properties instead of public fields. If I want to bind to say, a list control of some type, the Reflection that goes on at runtime will often treat properties different from public fields.
  • Keep my types dumb, the business logic operations dealing with these types is contained elsewhere, like business logic classes or validation controls
  • Follow a naming convention like CamelCase
  • Pass groups of Types around in a Collection class like ArrayList (this will be nicer with template types in Whidbey)
  • Avoid frameworks that force Type inheritence where possible

A simple example, then, may be:

          public class BlogEntry

          {

                   private String text;

                   public BlogEntry()

                   {                          

                   }

                   public string Text

                   {

                             get{return text;}

                             set{text = value;}

                   }

          }

And, yes, my Property doesn't do much, but its there mostly for run-time binding.

Using DataView.Sort its very easy to use code already in the runtime to sort DataRows. With Custom Types however there is no readily apparent built in solution. Dig slightly beneath the surface and you will find the IComparer interface and the ArrayList.Sort(IComparer). This, then, is one solution, but how can you implement this model without very large if/then statements that are specific to a Type? I would like to:

  1. Be able to sort an ArrayList of Types based on any primitive property they may have
  2. Write code that is not specific to one type
  3. Support case-insensitive String comparison and reverse-sorting
  4. Make the implementation shorter than a long if-then statement
  5. Execute this with only a line or two of code, just like when using DataView

Solution: Reflection and Delegates

The solution is easy using two excellent .NET features: Delegates and Reflection. Delegates will allow me to use different comparison functions dependent upon the Type of the field I want to compare; Reflection makes it easy to identify metadata about classes at runtime. For now supporting int, String, Date, and double types will suffice for most needs. Here is my Type Comparer.

using System;

using System.Collections;

using System.Reflection;

 

namespace damonpaynedotcom.Types

{

          /// <summary>

          /// Make it easy to Sort Custom Types

          /// </summary>

          public class TypeComparer : IComparer

          {

                   private delegate int DoCompare(object x, object y);

                   private DoCompare _compareMethod;

                   private PropertyInfo _propInfo;

        private Hashtable _methods;

                   private bool _caseSensitive;

                   private string _sortProperty;

                                     

                   public TypeComparer(string propertyName, Type objectType)

                   {

                             _caseSensitive = true;

                             _sortProperty = propertyName;

                             _methods = BuildSortMethods();

                             _propInfo = objectType.GetProperty(_sortProperty);

                             if (null == _propInfo)

                             {

                                      throw new ArgumentException(string.Format("Type {0} does not have a Property '{1}'", new Object[] {objectType.ToString(), propertyName}));

                             }

                             _compareMethod = (DoCompare)_methods[_propInfo.PropertyType];

                             if (null == _compareMethod)

                             {

                                      throw new ArgumentException( string.Format("Type not supported: {0}", _propInfo.PropertyType) );

                             }

                   }

 

                   protected Hashtable BuildSortMethods()

                   {

                             Hashtable ht = new Hashtable();

                             ht.Add(typeof(int), new DoCompare(CompareInt));

                             ht.Add(typeof(double), new DoCompare(CompareDouble));

                             ht.Add(typeof(string), new DoCompare(CompareString));

                             ht.Add(typeof(DateTime), new DoCompare(CompareDate));

                             return ht;

                   }

 

                   public bool CaseSensitive

                   {

                             get{return _caseSensitive;}

                             set{_caseSensitive = value;}

                   }

 

                   protected int CompareInt(object x, object y)

                   {

                             int xInt = (int)x;

                             int yInt = (int)y;

                             return xInt.CompareTo(yInt);

                   }

 

                   protected int CompareDouble(object x, object y)

                   {

                             double xDouble = (double)x;

                             double yDouble = (double)y;

                             return xDouble.CompareTo(yDouble);

                   }

 

                   protected int CompareDate(object x, object y)

                   {

                             DateTime xDate = (DateTime)x;

                             DateTime yDate = (DateTime)y;

                             return xDate.CompareTo(yDate);

                   }

 

                   protected int CompareString(object x, object y)

                   {

                             string xString = (string)x;

                             string yString = (string)y;

                             if (!CaseSensitive)

                             {

                                      xString = xString.ToUpper();

                                      yString = yString.ToUpper();

                             }

                             return xString.CompareTo(yString);

                   }

 

                   #region IComparer Members

 

                   public int Compare(object x, object y)

                   {

                             object xVal = _propInfo.GetValue(x, null);

                             object yVal = _propInfo.GetValue(y, null);

                             return _compareMethod(xVal, yVal);

                   }

 

                   #endregion

          }

}

If the need ever arises, I may experiment with algorithms for multiple-level sort or sorting based on non-primative types. I also need to work a little bid on the code-formatting styles!

Tags:

About the author

Damon Payne is a Microsoft MVP specializing in Smart Client solution architecture. 

INETA Community Speakers Program

Month List

Page List

flickr photostream