Welcome

Please contact me (Phil Haack) at here with any errors, problems, and/or questions.

To learn more about the application, check out the Subtext Project Website.

Powered By:

Syndication

Blog Stats

Bloggers (posts, last update)

Latest Posts

Biggest Myth in Racquetball

Televising Racquetball will make it the next "Big" Sport

I'm astounded by the amount of people that are so passionate about how Professional racquetball has to be televised and how it will be the savior that the sport need to bring it to the next level.  I say, what a bunch of bull crap.  To me, it sounds like the same old rehash of the Olympics debate, "If we could only get into the Olympics then...".  The fact that the ultimate goal is so entirely one-dimensional to a lot of people is just basically laughable.

The joke is further intensified when you see the quality of the video that is being produced professionally.  It is hard enough to see the ball at this level of quality, that it makes the hardcore "It must be broadcast at any cost, for the benefit of the sport" even more asinine.  At least the Professionals at the top recognize that a cam mounted shot from a local's handy-cam isn't doing the sport any favors.  Even the semi professional live streaming feeds look like there are people inside a box that has a lot of mosquitos.  Every once in awhile we see a ball in their hand, but then we start hitting the 130+ mark and it's back to my imagination to fill in the gaps.

Don't get me wrong, I love seeing the streams and the bootleg videos put up on web, I'm a fan.  I've played for numerous years so I can fill in the gap where I have no idea where the ball is because I can read the body language of the players, the position of their racquet, and the sounds of the court just like I can tell where a B level person is going to hit a ball before they do.  The question is, can my Mom?  Nope!

And that's why TV won't be making our beloved sport big any time soon.  Sure, us ravenous fans will scream to the tree tops about how we want to see the latest match (for free no less) as it's happening, but if I go to the local club no one is even talking about it.  Why not?  I have my ideas about that but, what about you?

posted @ 3/9/2009 10:11 PM by William C. Tilton

Secrets from the Racquetball Ninja #1

Why are you trying to kill the ball?

One of the biggest mistakes that I see lower level* players shoot for, is the killshot.  The killshot is bar none the hardest shot to hit in the game.  Even at the Pro level you have a very slim chance to hit a killshot.  A killshot is defined as a shot in which the ball bounces it second time before the short line.  Given that the percentage to hit it goes down exponentially as you degrade in player ability, makes it crazy  that most lower level players are trying to smack a winning killshot.

A much better approach would be to get back to basics.  Instead of trying to hit the lowest percentage shot, start thinking about your options when you are hitting the ball.   First start to think of it a bit like a strategy game.  Take into account your, and your opponent's court position.  Are you hitting the shot from a powerful position or a weak one?  A powerful position is when you are centered between the side walls and forward of the encroachment line, yet behind the serving line.  Your position gets weaker the further you move from this point.  Is your opponent in a powerful or weak position?

Now that you've determined your positions, figure in your percentages to hit a successful shot.  How fast is the ball traveling?  The faster it is traveling the lower the percentage goes.  Are my feet set?  If you are on the run the percentage goes way down.  Can I hit the shot below my knee?  Anything above lowers the percentage of a great shot.

Lets run through a few simple scenarios:

You receive a setup (high). Is my opponent in the back of the court (weak)?  Maybe a pinch.  Which side are they on?  If I can't hit a pinch then lets go for a pass to the opposite side of the court.

or

You receive a setup (high).  Is my opponent in the front of the court (powerful)?  Maybe I could hit a high pass around them?  What about a wide pass to change things up?

or

You receive a ceiling ball.  Am I hitting the shot above my waist (low)?  Should I go to the ceiling or is it such a big setup and I am in a powerful position while my opponent is weak that I could hit a really high pass and get away with it?

In none of these scenarios should you be thinking "killshot".  In fact you should dismis the killshot off to the fact of being a lucky shot or a fluke, because what you were trying to do was hit a great down the line pass and it went low.  The first thing you should start to see is less skips.  Skips are the biggest way to lose a match, and they are also much easier to hit when shooting for that bottom board.  Raise your shots up a bit and it becomes much easier to not skip.  Let your opponent skip the ball, don't just give it to them.

Racquetball Ninja's rule #1: Do everything in your power to not skip the ball.

The next thing you should see is more points for you.   Now that you are hitting less skips, you are effectively putting more pressure on your opponent to to do the same.  The other thing that is happening is that the ball, with proper passes, will be going behind your opponent.

Racquetball Ninja's rule #2:  It is easier to move forward than backwards.

And the same is true for your opponent.  If you are hitting the ball low, the ball will be up in the front of the court.  A opponent can then move forward easier and if you leave the ball up enough will be low enough for them to attempt a re-kill which is ten fold easier.  Why?  Because they are in the front of the court in a powerful court position, while having the ball low enough (high) to effectively hit a shot within their roundhouse.  I am a re-kill master, and I will eat your left up kill attempts for breakfast.  I encourage you to become a re-kill master as well, after you learn to effectively pass.

With a pass you are forcing your opponent into a weaker position on the court while giving yourself the time to get into a powerful one.  Makes it way easier to get the next shot and make a better return.

For each shot get into the practice of analysing these areas for your shot selections.  Given time they will become second nature and you too shall have inner peace.

posted @ 12/24/2008 11:14 AM by William C. Tilton

Worst Day of Playing

One of my worst days came back to me as I was playing a regular club player the other day.  We were in our 4th or 5th game and he was dripping with sweat, and I was feeling almost warmed up.  I've played him a few times, and this is usually how it goes.  My goal for the past few years has just been to have a good time playing, mainly because of the lack of solid Open level play at local clubs.  I'm not working on anything specific, no real focus, just trying to hit some fun shots and screw around a bit.

I gave myself the name "dink-a-tron" and was having a great time laughing about it, when I look back and my opponent is not looking too happy.  He just ran around the court chasing the 4 well placed dinks which he then hit back to me for my final "high and slow" pass (woot!) that just died in the corner.  His look made me laugh some more, I couldn't help it.  I then sobered up a bit because I remembered an instance where I was an A player trying to break into the Open bracket.

I was pretty young and was playing one of the local Open players.  This was back in the day where every club had a few Open level players and I had a regularly scheduled match once a week.  This week I was going to kick some butt.  I had been practicing shots, drilling on  my own for hours on end in the past week and I was determined.  I was going to make the games really close, perhaps even beat him.  This was my week.

I never remember trying harder in my life to score just 1 point. I was running all over the place, diving around the court, hitting the best shots I could, and my opponent was virtually standing around making me move.  I'm not sure if I got a point or not, I think I ended up with a nut of dough (zero).  After the game is was so incredibly angry and frustrated that tears of rage were coming out.  I hated being this crappy at something I was trying so hard at.

I took a break from the game for awhile, but I eventually got to the level I was trying to achieve.  I'll never forget that beating that I took on that day though, while I'm sure my opponent has long since forgotten.  As with a lot of things in Racquetball there are often parallels in life - everything is attainable, but holy crap there's a lot of work involved :P

posted @ 12/24/2008 10:32 AM by William C. Tilton

One thing that sucks about watching Pro Racquetball

You can't be loud. Sure you can be super loud in between rallies, but once the score is called everyone that plays the game knows that it's time to shut up.

And I think this is fine for normal amateur play, and tennis, and golf, and other wussy non-televised sports. But I start to think about how in Basketball when the opposing team is shooting a freethrow, people behind the glass backboard are screaming their asses of and waving crap around trying their hardest to get the player to screw up and miss the shot.  In Baseball, I got a huge kick out of sitting behind homeplate and yelling out "Hey batta batta, HEY batta BATTA, SWIIING!"

No one ever looked at me like I was crazy.  It was part of the game, and shoot, other people we're yelling things too.  I can tell you that by participating in this way, I felt more in touch with the game.  Even at my kid's soccer game I got pretty amped yelling out "come on kick it...there ya go...Hoooly moly, keep going, get it in, come onnnnn.  GOOOOOOOO!  GOOOOOOOOOAAAAAAL."  I was excited and it was during play and omg if other parents weren't causing a ruckus for their kids as well.

How can I tell that we've all be trained not to say anything during the rally, other than the "Quiet please" from the IRT refs?  My uncle, who had never in his life either played racquetball or seen it before came to watch me play one time.  What did he do?  He screamed out mid rally "Com'on Willie!!  Kick some butt!"  I looked up at him and was like, wtf are you doing man?

Then I think of the Pro game, and am like, why not?  Why can't people scream out, "skip the ball you skippy skipperton" before someone hits a shot?  Who's to say that if someone hits a lousy shot we can't rag on them.  Sure it'd be a big change from the current status quo, but I'm telling you as I'm watching the current event live on ESPN360, I'm screaming at the television!

Why on earth am I more into the game at home sitting on my ass than actually being there?

Sure there should be limits, just like in other sports.  Like no going up and banging on the glass or throwing crap into the court.  But please stop quieting the crowds down because I think you're killing your audience participation and making it less exciting for the people that are on the outside of the shiny glass cube.

posted @ 9/20/2008 7:53 PM by William C. Tilton

EKTELON ANNOUNCES SUPPORT OF ALL MILITARY CHAMPIONSHIPS

For the first time in over 15+ years we will be hosting an ALL MILITARY RACQUETBALL NATIONAL CHAMPIONSHIP presented by Ektelon & dedicated specifically for military folks over the Veteran's Day weekend (November 14 - 16, 2008) With the support and backing of the Moral, Welfare & Recreation, and EKTELON, we will compete against other members of the armed forces in a racquetball tournament. Ektelon will be supporting this event with prizes & as the Official Ball using Premium Select. In addition, Ektelon is committed to full support of a number of exciting projects in conjunction with the military.

There will be plenty of play with Men's / Women's Singles and Double and Mixed Doubles, especially since we will be using the Round Robin / Pool Play format for all participants except in the OPEN and ELITE divisions. We have also made arrangements for lodging, where out of town players will be able to stay on base for no more than $30/night, unlike some other major tournaments where the lodging costs exceeds over $120 for a room. We really can't do anything about flight arrangements, but hopefully international players will be able to catch a MAC flight to the States, and then find a cheap flight to San Diego . Right now, all services really don't have funding to cover this event, but hopefully the costs / registration fees won't deter people from coming out and having a great time. I do highly recommend that you ask your command for NO COSTS / PERMISSIVE TAD orders, so you don't burn your leave time up for this event.

Additionally, we would be delighted to have any financial/product assistance you may feel like donating to support this effort to provide a healthy diversion for our men and women in uniform.

Please be on the look out for additional entry information in about 1-2 weeks. There will be online entry available for this event on R2 Sports.

We hope you will be able to join us for this is an event. If you are a military player or know any please let us know as we are starting a database to reach all players. If there is anything we can do to get your here, please let me know. LCDR Steven Harper (USN), out of San Diego , can be reached at:

cell: (757) 831-8458

e-mail: militaryrball@pacbell.net

Please do not hesitate to give us a call. Hope to see you in November!!

posted @ 7/21/2008 3:47 PM by William C. Tilton

Let's Dance

I have this image in my head.  It could very well be a 10 year olds fantasy, but I want to be in the arms of the one I love and be able to face the world together as if nothing can come between us.  I'm enamored with the show "So you think you can dance" and there was a beautiful waltz danced that I find myself thinking of often.   Maybe that is what I have pictured in my mind.  A couple dancing through life together.  If they stumble in the middle of a dance (have a life problem), that's OK, they don't let go of each other and they move forward together in the dance (in life - they face it together no matter what it is).  If they let go of the other person then the dance can't be continued...life can't move on for them.  The dance is broken...they are broken.  They need to hold on to their partner as if their lives depend on it.  They wouldn't want to disrupt their dance (their bond...their love).  When you're dancing you have to trust your partner.  You have to believe they will be there for you during the entire song.  They are committed to you for life.  So when you have found that partner you want to dance with for life...don't let go, no matter how many times you both have stumbled.

posted @ 6/19/2008 1:26 PM by Kathleen Pierce

Last Month

Well, I'm in month nine of my pregnancy.  I don't know if it will be a boy or girl and that is driving me nuts!  LOL  But, it will be a fun surprise when that time comes.    Right now, I'm just trying to keep up with my two year old.  

posted @ 5/11/2008 4:26 PM by Kathleen Pierce

Slow it down with Wacqetball

Dan Davis of Colorado has invented Wacquetball, a slower version of racquetball that uses a foam ball instead of the rubber version in racquetball.  It looks like seniors are getting into it, and women as well.  Maybe this is a good way to introduce them to the sport, or could this be a sport on it's own?  Is the game getting too fast?  I wonder what it would look like if some professionals tried it out.

Check out the video from 7 News of Denver.

posted @ 3/27/2008 9:35 AM by William C. Tilton

American Gladiator meets Son Nguyen

image I just watched Son take on the Gladiators in the remake of the 80's show American Gladiators.  The show was pretty entertaining for the most part, and seeing someone you know bashing being thrown down a foam mountain is pretty intense.   Son's competitor was in crazy shape though.  He was the fastest person through the Eliminator, with Son not far behind.  This is where I thought the show kinda stunk.  Even if Son beat one of the top 4 times, he still "lost" because the person he went up against beat him.  I just think this could be a point to where the contestants could compete against the top 4 and not each other - might have some surprising things happen if that were the case.

I thought it was a bit unfair because they also never had to directly compete.  It was always the Gladiators against the two contestants and if you look at the competition where you have to run through the Gladiators Son went through the first 2 way faster than his competitor but got stuck on the last two dudes and didn't even make it to the end.  Again on the pyramid, Son had a few shots but got trapped up because of his opponent. 

I'm making a few excuses but we wanted him to win :)

The show was pretty entertaining, but just seemed unfair to the contestants in certain ways.  Almost to a point to where it seemed almost lucky that a person won a competition, not because they had more skill or endurance.  After the show I wondered how some other racquetball players would have done.  Mainly was thinking Dan Obremski and Jack Huczek.  Would be interesting...

posted @ 1/28/2008 12:27 PM by William C. Tilton

This Blog Has Moved

Weblog:
http://blechie.com/wpierce/

Feed:
http://feeds.feedburner.com/wcpierce/

posted @ 1/3/2008 9:36 AM by Bill Pierce

Playing Good with the Copper "Club"

Ektelon O3 Copper Racquetball RacquetFelt great last night.  Second time playing with the 03 Copper racquet and I'm getting used to the weight.  It's been a loong time since Ektelon had the balls to not go lightweight.  Everyone seems to like the feather light racquets but overtime I believe they can kill your joints.

With the heavier racquet I don't have to swing so fast.  In Open level play that means even though my racquet is heavier, my racquet is faster because I can swing slower (F=ma).  This may seem like quite the opposite, but think about this, to swing the lighter racquet, I have to swing it faster to equal the same amount of power.  With the heavier one, I don't.  I can take shorter swings, don't have to swing as hard, and I'll have more control.

It takes a few matches to really get control of it though.  As soon as you figure out that you don't have to really smash the ball to get it going, everything start really rolling for me. 

If you have a big frame, are tall, and can lift 250 grams...try it out, just remember to relax your swing and don't try to swing as fast (takes practice).  If you demo it, you're going to be frustrated the first 10 games you play.  Give it a chance though and after game 10...

posted @ 9/27/2007 10:59 AM by William C. Tilton

The Outdoor Experiment

Racquetball doesn't have too many large scale events.  I'm really perplexed as to why, but I believe it mainly comes down to money.  The logistics involved with setting up a grand slam event is huge.  With Outdoor racquetball, I would think that it would be easier to squeeze into existing venues.

This past weekend there was a Venice beach event.  Ektelon and WOR put it on and and Shawn Royster at Royster productions videoed everything in High Definition with 10 camera's rolling.  To me this sounded like the first grand slam outdoor exhibition.  It seemed like the matches went well and the crowds were there and there was only one accident with Son Nyugen get a racquet to the face.  Son ended up with a few stiches but no worse for the wear so all in all a successful event...right?

While I'm glad everyone played well and Son's OK, I'm also really interested in the crowd. Whats the court look like? Where was it positioned? Were there bleachers? Where did people watch from? How close were you to the other event? Did they not care that you guys were doing something that potentially stole their viewers, or was it cohesive? Was the ball more visible through the HDTV content, with the built court? While everyone keeps calling it an event, I'd hope that someone else out there was treating it more of an experiment to see if it would be feasible to pull more of these events off in other high traffic locales.

My main points would be:

  • Would having racquetball and another sport together increase both sport's attendance?
  • Was the high traffic helpful in attracting people, and how long did those people stick around?
  • Was anyone polled about anything? (Would you pay for a ticket to watch this? How interesting is the game to you? Would you like to learn the rules? Have you ever played?)

When Son got hurt 1/3 of the crowd was lost. Nothing against Son's injury, but did they just get bored with nothing going on? How much time elapsed? With 300 people watching, and losing 100 of them...that's huge. These types of things could happen in the future and there needs to be a plan (maybe another match going, or bring another match on, or maybe make the models dance around on trampolines).

posted @ 9/4/2007 10:41 AM by William C. Tilton

Are these outdoor courts?

We went up to Santa Barbara this weekend for a collegiate tournament that Jackie played in.  It was an indoor tournament, and I basically had fun with the kids while she got a few games in.

The facility was pretty sweet, it had two gigantic pools, soccer, football, and even archery.  I was thinking, I bet there are outdoor courts here too.  Being the busy Dad I was, I didn't go searching, but after getting back and looking at some aerial photos, it looks like I was a few yards away from one and didn't know it.

We were playing a the playground about 40 feet away from what I thought was a building, but never went to the other side of it.  It looks like there are court lines, but the other court has none.  It also looks like a window or something on the right court.  Anyone know for sure?

http://local.live.com/default.aspx?v=2&cp=pr2mzc50c4t0&style=o&lvl=2&tilt=-90&dir=0&alt=-1000&scene=7994759&sp=Point.pr2n4h50c52n_Racquetball%20Courts%3F___&encType=1

posted @ 8/13/2007 2:13 PM by William C. Tilton

It was a tough Decision, but we're not going to the U.S. Open Racquetball tournament this year

Ever since Ian was born in 2003 that particular racquetball event has always been on the chopping block. It's for the love of the sport, and the love of the camaraderie that we continued going. This year however, we decided to hand the torch off to someone else.

A few reasons came into play. Ian and Lexi were a huge reason. It's kind of tough to expect them to contain themselves while we are working on things, and I can't expect them to sit quietly in the tower. Willie and I never got paid monetarily (though it was nice to have a room paid for and food paid for), and always used vacation time to go "work" somewhere else. If that makes sense. Now with the kids our desire to go off and do other things with them has increased, and that was also a reason. Plus with the addition of them into our family, a rental car is completely necessary, I'm not going to chance terrible weather walking blocks to the club with the kids in a stroller freezing, so that was an added expense.

It's going to be tough this year. We've provided coverage for that event for seven years. Willies been at the open since its inaugural year (first as a player than as employee). It's always been something that we look forward too, and it will be greatly missed on our agenda.

posted @ 8/2/2007 5:56 PM by Jackie Tilton

Back on the court

I haven't played in awhile due to my shoulder killing me and my back hurting.  Not sure why everything is affecting me so, but I think a big portion of it is that I'm working longer hours and more intensely.  The repetitive stress to my ligaments and joints aggrevates any type of exercise after the fact.

Today I got on the court to see what the potential differences were between running on an elliptical and playing on the court.  Imagine my suprise when playing on the court felt better than running on an elliptical.  I thought that the elliptical would be a lower impact exercise and thus hurt less.  Maybe I was wrong?  I do want to try just swimming a few laps on the next workout session and compare that.  I also saw some dudes playing volleyball, so I might give that a whirl.  I think basketball is out, and I don't want bad knees and I really suck :)

Either way, it's looking up for playing racquetball again!

posted @ 7/26/2007 8:38 PM by William C. Tilton

My Only Gripe about Outdoor Nationals

Well, I can totally understand making it to the finals when you didn't expect it, and having to catch a flight, but the way the women were bumped all the way to the end of the day, even after the Mens Doubles really sucked. The Carson Huczek Match took place instead of the womens finals, and then instead of putting the womens finals on, they waited until after the Men's Open Doubles...which means...everyone left. I'm hoping that everyone stayed and supported them. I would have stayed except my situation is a little different with the kids and such, and we were done.

posted @ 7/23/2007 3:53 PM by Jackie Tilton

Racquetball to be played in 2011 Pan-Ams in Guadalajara

Very cool.  The Pan-Ams used to be the sports largest event.  Not in terms of racquetball people of course, but in terms of those not playing racquetball that attend the event.  To be re-inducted back into the Pan Am is a big step towards getting Racquetball out there.

Meet and play forums

posted @ 7/17/2007 11:57 AM by William C. Tilton

WOR National Championships

Due to some injuries I sat out this year.  Jackie played a few matches, lost every match, but had fun, which is what it's all about.  The Men's pro was again the focus of the tournament, with the #1 indoor player Jack Huczek joining the fray.

The draws were pretty standard with no suprises.  Rocky, like last year, was looking especially sharp.  He is the new Brian Hawkes, and it's a shame that Hawkes won't get in there now to play.  He advanced through the tournament pretty easily to meet Jack in the finals.

The Jack Huczek and Greg Solis match was a little suprising as I thought that Greg would have beaten Jack.  Greg has way more experience outdoors, but he looked really nervous or overconfident or something...  Either way he played pretty badly, all the while Jack just kept the same heading of getting a few more points than the error prone Greg.

We were going to take off after that match, but then Jack and Rocky decided to play early.  Was a nice deal for me as there were no jumpies on Sunday for the kids (one of the jumpies had died, and the kids were trapped or something on Saturday) so it was hard to justify sitting around for 2 more hours watching them. 

Rocky played outstanding against Jack.  I wish he'd show the same amount of confidence and resolution in indoor.  His serves were masked extremely well, appearing just over the short line and within the wide serve line.  These prove especially difficult to retrieve, and Jack was having a really hard time doing that.  Outdoor singles gets very frustrating because if your serves aren't on, you're going to lose.  Jack early on showed some great gets but Rocky's outdoor experience would have Jack scrambling and then Rocky hitting excellent out the door shots.  I actually saw Jack "give up" on 2 shots.  He looked beaten later in the game, and Rocky just kept pounding away.

The crowd was also wanting Rocky to win badly.  I felt like shouting out some helpful hints for Jack but didn't think he'd listen, plus I'd be the only one cheering for Jack (Hey, I gotta live and play with these dudes the rest of the year :)).  The last match point was particularly uneventful as Rock pounded a head high serve, Jack returned and Rocky dinked it to the corner to finish it out.

posted @ 7/16/2007 12:48 PM by William C. Tilton

AES Encryption in VBScript

VB6/VBScript was one of the first languages I learned to use.  Today, VBScript is still my fall back language when I just need to 'Getter Done!'.  Coupled with Windows Script Host and the Scripting runtime I can use it to automate a large number of otherwise manual tasks.  We have some VBScripts laying around that export data from our datastore on scheduled intervals and make it available to our customers to download via FTP-SSL.  We are adding some new information to the export that is of the sensitive nature and so encryption came up.  Figured since 'Standard' is the S in AES, it made a good choice.  The problem was finding some code to do this in VBScript.  Some digging turned up an implementation in VB6/ASP but it was god awfully large and complicated.  Additionally it was difficult to verify that once encrypted on our side, our customer could easily decrypt it using a previously exchanged Key and Initialization Vector (also using a different programming language all together).  Since the .Net Framework makes encryption dirt simple and it was already on the server I whipped up a simple class that is exposed to COM and easily incorporated into our existing VBScript.

Without going too deep, AES requires a Key and an Initialization Vector (IV) to encrypt something.  You need the same Key and IV to decrypt the info at a later time.  Both of these are byte arrays (byte[]).  The resulting encrypted data is also a byte array.  Now sharing/hard coding a byte array in code is not all that easy.  Rather than share the raw byte array you can base64 encode the data and then you have something that is easily inserted into a text file or transferred via email.  The code below is written in a very targeted manner expecting/returning base64 data, hard coding the algorithm used, ascii encoding, etc.  Please feel free to tweak for your needs.  To expose this to COM, just run "regasm.exe My.Product.dll" and you can run the...cough...unit tests...cough at the end of the sample.  Program note: all of the methods here could be marked static, but COM doesn't like static methods.

namespace My.Product
{
  using System;
  using System.IO;
  using System.Runtime.InteropServices;
  using System.Security.Cryptography;
  using System.Text;

  [ProgId("My.Product.Crypto")]
  public class Crypto
  {
    public string Encrypt(string base64key, string base64iv, string clearText)
    {
      SymmetricAlgorithm algorithm = GetAlgorithm();
      algorithm.Key = Convert.FromBase64String(base64key);
      algorithm.IV = Convert.FromBase64String(base64iv);

      byte[] clearTextBytes = Encoding.ASCII.GetBytes(clearText);

      byte[] cipherTextBytes = Transform(algorithm, clearTextBytes, false);

      return Convert.ToBase64String(cipherTextBytes);
    }

    public string Decrypt(string base64key, string base64iv, string base64cipherText)
    {
      SymmetricAlgorithm algorithm = GetAlgorithm();
      algorithm.Key = Convert.FromBase64String(base64key);
      algorithm.IV = Convert.FromBase64String(base64iv);

      byte[] cipherTextBytes = Convert.FromBase64String(base64cipherText);

      byte[] clearTextBytes = Transform(algorithm, cipherTextBytes, true);

      return Encoding.ASCII.GetString(clearTextBytes, 0, clearTextBytes.Length);
    }

    public int DefaultKeySize
    {
      get
      {
        SymmetricAlgorithm algorithm = GetAlgorithm();
        return algorithm.KeySize;
      }
    }

    public int DefaultBlockSize
    {
      get
      {
        SymmetricAlgorithm algorithm = GetAlgorithm();
        return algorithm.BlockSize;
      }
    }

    public string GenerateBase64Key(int keySize)
    {
      SymmetricAlgorithm algorithm = GetAlgorithm();
      algorithm.KeySize = keySize;
      return Convert.ToBase64String(algorithm.Key);
    }

    public string GenerateBase64IV(int blockSize)
    {
      SymmetricAlgorithm algorithm = GetAlgorithm();
      algorithm.BlockSize = blockSize;
      return Convert.ToBase64String(algorithm.IV);
    }

    private static byte[] Transform(SymmetricAlgorithm algorithm, byte[] bytes, bool decrypt)
    {
      byte[] transformedBytes = null;
      using (ICryptoTransform transform = GetTransform(algorithm, decrypt))
      {
        using (MemoryStream memoryStream = new MemoryStream())
        {
          using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
          {
            cryptoStream.Write(bytes, 0, bytes.Length);
          }
          transformedBytes = memoryStream.ToArray();
        }
      }
      return transformedBytes;
    }

    private static ICryptoTransform GetTransform(SymmetricAlgorithm algorithim, bool decrypt)
    {
      if (decrypt)
      {
        return algorithim.CreateDecryptor();
      }

      return algorithim.CreateEncryptor();
    }

    private static SymmetricAlgorithm GetAlgorithm()
    {
      RijndaelManaged algorithm = new RijndaelManaged();
      algorithm.KeySize = 256;
      algorithm.BlockSize = 128;

      return algorithm;
    }
  }
}

 And it's usage in VBScript:

Option Explicit

Call Main()

Sub Main()
  Dim crypto
  Dim base64key, base64iv
  Dim clearText, cryptText, cryptText2, decryptText

  Set crypto = CreateObject("My.Product.Crypto")
  base64key = crypto.GenerateBase64Key(crypto.DefaultKeySize)
  base64iv = crypto.GenerateBase64IV(crypto.DefaultBlockSize)
  clearText = "EncryptThis"

  cryptText = crypto.Encrypt(base64key, base64iv, clearText)
  decryptText = crypto.Decrypt(base64key, base64iv, cryptText)
  If clearText <> decryptText Then
    MsgBox "Decrypting did not yield correct value"
    Exit Sub
  End If

  cryptText = crypto.Encrypt(base64key, base64iv, clearText)
  cryptText2 = crypto.Encrypt(base64key, base64iv, clearText)
  If cryptText <> cryptText2 Then
    MsgBox "Encrypting twice produces different results"
    Exit Sub
  End If

  MsgBox "All Tests Passed"    
End Sub

posted @ 6/29/2007 8:20 AM by Bill Pierce

MonoRail - Efficient Tab Indexing

I'm a big fan of keyboard shortcuts for the Windows, Resharper, Firefox, Web Browsing, GMail, etc.  The less I touch the mouse the more productive I am.  One thing that can make a great web application suck hard is poor or absent tab indexing on form fields.  It takes a little extra time on the developers part but it makes a world of difference to the end user.  Rather than hard code tabIndexes, I use the following technique using a simple accumulator:

<?brail
  tabIndex = 1
?>

${Form.FormTag({'action':'login'})}
<table>
  <tr>
    <td>${Form.LabelFor('username', 'Username')}</td>
    <td>
      ${Form.TextField('username', {'tabIndex':tabIndex++})}
    </td>
  </tr>
  <tr>
    <td>${Form.LabelFor('password', 'Password')}</td>
    <td>${Form.PasswordField('password', {'tabIndex':tabIndex++})}</td>
  </tr>
  <tr>
    <td />
    <td>${Form.Submit('Login', {'tabIndex':tabIndex++})}</td>
  </tr>
</table>
${Form.EndFormTag()}

One problem I struggled with in ASP.Net was allowing tabIndexes to properly flow from a page to a user control then back again.  I'm going to ping Oren to see if it is possible to declare tabIndex 'globally' (in a layout maybe?) and allow all views/sub views/view components to use the same value to try and address this in MonoRail.

posted @ 6/26/2007 4:13 PM by Bill Pierce

Dexagogo - Alert Validation Advice

I recently blogged about using Dexagago validation API with MonoRail.  The API allows you to specify your own advice messages in any HTML element.  The framework will take care of showing/hiding the element as needed during validation.  I wanted to be able to display a javascript alert box with validation messages in certain cases.  Here's what I came up with:

<script type="text/javascript">
  function AlertAdvice(isValid, el)
  {
    if( !isValid )
    { 
      alert(el.title);
      if(el.select) el.select();
    }
  }
</script>

${Form.FormTag({'action':'login','immediate':'false','stopOnFirst':'true','onElementValidate':'AlertAdvice'})}
<table>
  <tr>
    <td>${Form.LabelFor('username', 'Username')}</td>
    <td>
      ${Form.TextField('username', {'class':'required','title':'Please enter a Username'})}
      <div id="advice-username" style="visibility: hidden;" />
    </td>
  </tr>
  <tr>
    <td>${Form.LabelFor('password', 'Password')}</td>
    <td>${Form.PasswordField('password', {'class':'required'})}</td>
  </tr>
  <tr>
    <td />
    <td>${Form.Submit('Login')}</td>
  </tr>
</table>
${Form.EndFormTag()}

First we specify a javascript function 'AlertAdvice' that will be called by the validation API for each validator on our form.  If the validator fails (empty required field, alpha in a numeric field, etc) we display the contents of the title attribute, then for good measure we select the contents of the field.  When specifying your form tag you want to make sure to set immediate to false.  I found this out the hard way (took me a few tries :) otherwise you will be locked in a tight loop with a constant alert on invalid fields.  I also set stopOnFirst to true so that the user doesn't get overwhelmed with prompts for a large number of invalid fields.  Finally, we hook up our AlertAdvice function with the onElementValidate property.

You need to put the message you want displayed in the prompt in the title attribute of your field, ${Form.TextField('username', {'class':'required','title':'Please enter a Username'})} in our example above.  Finally, I wasn't able to find a way to disable the API's automatic display of an advice message.  To work around this, I add a hidden div element with a name of advice-<fieldName>. 

Lightly tested in IE6 and FF2.

posted @ 6/26/2007 12:18 PM by Bill Pierce

MonoRail - Initial Focus ViewComponent

Need to set initial focus to a field on your form?  This component is adapted from Fábio's code on the MonoRail forums.

namespace My.Product.Mvc
{
  using Castle.MonoRail.Framework;

  [ViewComponentDetails("InitialFocus")]
  public class InitialFocusComponent : ViewComponent
  {
    private const string FOCUS_TEMPLATE =
      "<script type=\"text/javascript\">Event.observe(window,'load',function(){{$('{0}').focus();}});</script>";

    private string _id;
    private bool _shouldRender;

    [ViewComponentParam(Required=true)]
    public virtual string Id
    {
      get { return _id; }
      set { _id = value; }
    }

    public override void Initialize()
    {
      if( !Context.ContextVars.Contains("__Initial_Focus_Set__") )
      {
        Context.ContextVars["__Initial_Focus_Set__"] = Id;
        _shouldRender = true;
      }
    }

    public override void Render()
    {
      if( _shouldRender )
      {
        RenderText(string.Format(FOCUS_TEMPLATE, Id));
      }
    }
  }
}

Use in your view like so:

<% component InitialFocus, {'id':'username'} %>

This component is "first in wins" meaning if you include multiple component references in the same view/subview, the first field specified will get initial focus.  So far this has only been lightly tested on text fields.

posted @ 6/25/2007 10:41 AM by Bill Pierce

Ice is my friend

For some reason I've never really gotten all that sore in my life in althetics.  I've played tournaments and had the sore muscles after the fact, but never the cramping, never an injury, never intense pain.

With my back now I was told stuff about using ice and heat, along with some stuff like IB Profen, but never really did it...until now.

I was thinking that my back would take another few weeks to heal up, but I've been icing the crap out of it along with taking medicine to thin the blood.  Sure enough it's helping a lot!  I can ice it for 10 minutes when it really starts hurting and for awhile it'll actually go away entirely.

I love you Ice.

posted @ 6/23/2007 5:59 PM by William C. Tilton

MonoRail - Collocate your Strings

Localization is a pain.  Anybody who says different is a sadist.  It's especially difficult if you are trying to retrofit an app that didn't even try i.e. hard coding all strings in code/views.  Even if I'm not developing an application with localization in mind, I still strive to put all strings in a resx file and never hard code them anywhere.  The recommended method for localizing a standard ASP.Net application was to have a single resx file per page.  Similarly for a WinForms app you would have one resx file per Form.  In a WinForms app this is slightly more understandable since you may need to resize fields to accommodate different languages.  However in web apps the only thing I ever store in a resx file is strings. 

ASP.Net 2.0 introduced the concept of an App_GlobalResource that can be accessed from any page in your site.  This was a step in the right direction because you could easily reuse common strings as needed.  There are cases however when I need to generate a message in my business layer that will ultimately be displayed to the user.  So I end up needing a resx file in my Core assembly, and a resx file in my web app.  Kind of defeats the purpose of a centralized location for strings.  The problem is further compounded by the fact that VS2005 generates a strongly typed wrapper for your resx file that has all strings marked as internal.  So I can't easily put all of my strings in my Core assembly and then reference them in my web app.

I little googling turned up a work around that allows you to generate a wrapper with public properties.  This method worked just fine but I get anal about such things and wanted my publicly generated code to match as closely as possible to what VS2005 would have created for me.  Here is my adapted code to generate a file called Strings.Designer.cs that contains a public wrapper class called Strings in namespace My.Product.Core for my Strings.resx resource file:

<Compile Include="Strings.Designer.cs">
  <AutoGen>True</AutoGen>
  <DesignTime>True</DesignTime>
  <DependentUpon>Strings.resx</DependentUpon>
</Compile>

<ItemGroup>
  <EmbeddedResource Include="Strings.resx">
    <SubType>Designer</SubType>
    <LastGenOutput>Strings.Designer.cs</LastGenOutput>
  </EmbeddedResource>
</ItemGroup>

<!-- Generate Strings.Designer.cs with Public access -->
<Target Name="BeforeBuild" DependsOnTargets="GenStrongTypeResource" />
<Target Name="GenStrongTypeResource" Inputs="Strings.resx" Outputs="Strings.Designer.cs">
  <GetFrameworkSdkPath>
    <Output TaskParameter="Path" PropertyName="SdkPath" />
  </GetFrameworkSdkPath>
  <Exec Command="&quot;$(SdkPath)\bin\resGen.exe&quot; /str:c#,My.Product.Core,Strings,Strings.Designer.cs /publicClass Strings.resx" />
</Target>

The first part of the post is pretty generic, lets see how we can now use our strongly typed Strings class in our MonoRail views.

MonoRail supports Localization in a similar manner to ASP.Net.  You specify which resource file you want to read from and then assign it a friendly name you can use in your view.  Using my technique described above, you essentially bypass all of that.  My view engine of choice is Brail.  To be frank, I'm not sure if you will be able to use this method with NVelocity or any of the other engines.

First off, we need to configure Brail with our Core assembly.  You do so in your web.config file:

<brail debug="true" saveToDisk="false" saveDirectory="BrailGen" batch="false" commonScriptsDirectory="CommonScripts">
  <reference assembly="My.Product.Core" />
</brail>

Next, you add an import statement to your view and then you can use the generated Strings class just like you would in your C# code.  Here is the localized version of the login view I used as an example in my last post:

<%
  import My.Product.Core
%>

${Form.FormTag({'action':'login'})}
<table>
  <tr>
    <td>${Form.LabelFor('username', Strings.Username)}</td>
    <td>${Form.TextField('username', {'class':'required'})}</td>
    <td><div id="advice-username" class="advice" style="display: none;">${Strings.UsernameRequired}</div></td>
  </tr>
  <tr>
    <td>${Form.LabelFor('password', Strings.Password)}</td>
    <td>${Form.PasswordField('password', {'class':'required'})}</td>
    <td />
  </tr>
  <tr>
    <td />
    <td>${Form.Submit(Strings.Login)}</td>
    <td />
  </tr>
</table>
${Form.EndFormTag()}

Nice and easy. Now all of the strings used in your application are centralized in a single file. This makes translation more straight forward and helps prevent duplication of strings in multiple resx files. You could easily extend this and have a Strings assembly that only contains a resx file that could be reused in multiple applications.

posted @ 6/23/2007 8:33 AM by Bill Pierce

MonoRail - Form Validation the Hard Way

Why would you want to do something the hard way?  Well of course you do something the hard way when you can't do something the easy way (unless you are Oren in which case you do everything your way :).  Hammett has several excellent posts on how to do form validation the easy way using the Castle Validator component (screencast and additional thoughts).  The component makes validation dirt simple especially if you are using ActiveRecord.  However the default implementation ties validators to attributes on the model which works 80% of the time. 

For the 20% of the time when you want to get validators from somewhere else one would need to implement a custom IValidatorRegistry.  IValidatorRegistry is responsible for providing all validators for given type and/or property back to the validation framework.  Are you feeling the love?  All you need to do is customize where the validators come from, and you still benefit from the runtime and client side validation generation. w00t!  So, in theory your DatabaseValidatorRegistry could query a...database...to retrieve all validators for a given type and property.  Allowing you to craft an interface where by the end user could modify validation rules at will.  I'm getting a little dizzy just thinking about the possibilities.  I haven't gone there yet but when I do you will be the first to know.

That last paragraph literally popped into my head as I was starting this post.  I actually was going in a different direction for this particular discussion but I just had to put it down on paper.  What I really want to talk about is doing simple client side validation using the client side Validator scripts.  I have a simple login prompt with username and password.  I want to do client side validation to ensure they enter a username and password before submitting the form.  What do you do?  Go.

First things first, you need to install the client side scripts.  It is recommended to do this in your layout so that the scripts are included on all of your pages:

<head>
    <title>MonoRail Validation</title>
    ${Ajax.InstallScripts()}
    ${Form.InstallScripts()}
</head>

What exactly does this do?  Among other things it emits script tags for the Prototype libraries and the Dexagogo 'really easy field validation' libraries.  The next step is to create a form in your view with the necessary fields:

${Form.FormTag({'action':'login'})}
<table>
  <tr>
    <td>${Form.LabelFor('username', 'Username')}</td>
    <td>${Form.TextField('username', {'class':'required'})}</td>
    <td><div id="advice-username" class="advice" style="display: none;">Please enter a Username</div></td>
  </tr>
  <tr>
    <td>${Form.LabelFor('password', 'Password')}</td>
    <td>${Form.PasswordField('password', {'class':'required'})}</td>
    <td />
  </tr>
  <tr>
    <td />
    <td>${Form.Submit('Login')}</td>
    <td />
  </tr>
</table>
${Form.EndFormTag()}

How hard is it to make a field required?  Excruciating!  First the Form.FormTag automatically hooks up the required logic to the validation libraries.  See the 'class':'required' in the TextField and PasswordField elements?  The Dexagogo code uses CSS selectors (similar to Behaviour) to execute validation when the user clicks the Login button.  THAT'S IT!  Now, when you click Login without entering a username, the form will not be submitted and you will be presented with a lovely error message.  The Dexagogo site documents the twelve built in validations you can perform (dates, numbers, email, etc).  If you need more you can specify your own validation callback that will get executed when the form is submitted.  Dexagogo has a number of standard validation messages, but you can easily substitute your own by adding an element to your page with an id of "advice-<fieldName>".  If validation fails, this element will be shown to the user.  I applied a class of "advice" to my element so I could easily style error messages.  One oddity was that I had to inline specify the display: none.  Putting this in my external stylesheet caused the error message to not be shown properly.  The use of CSS selectors also makes it very easy for you to style your required fields (with a yellow background maybe?)  and style your numeric only fields and provide a standard legend to your users.

You can also specify some additional options in the FormTag (Hammett touched on these briefly in his screen cast).  If you want "advice" shown to the user immediately when the leave a field and you want to turn off the default of focusing on invalid fields, you would specify your FormTag like so.

${Form.FormTag({'action':'login','immediate':'true','focusOnError':'false'})}

Finally I'll reiterate the best practice you've heard before, always validate your data server side in addition to any client side validation you may perform.  For your reference here is the fully generated code for the view above:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head>
    <title>MonoRail Validation</title>
    <script type="text/javascript" src="/MonoRail/Files/AjaxScripts.rails?RC3_0006"></script>
    <script type="text/javascript" src="/MonoRail/Files/FormHelperScript.rails?RC3_0006"></script>
  </head>
  <body>
    <form action='/login/login.rails' method='post' id='form1' >
      <table>
        <tr>
          <td><label for="username">Username</label></td>
          <td><input type="text" id="username" name="username" value="" class="required" /></td>
          <td><div id="advice-username" class="advice" style="display: none;">Please enter a Username</div></td>
        </tr>
        <tr>
          <td><label for="password">Password</label></td>
          <td><input type="password" id="password" name="password" value="" class="required" /></td>
          <td />
        </tr>
        <tr>
          <td />
          <td><input type="submit" value="Login" /></td>
          <td />
        </tr>
      </table>
      <script type="text/javascript">
        if (!window.prototypeValidators) prototypeValidators = $A([]);
        var validator = new Validation('form1', {onSubmit:true, focusOnError:true, stopOnFirst:false, immediate:true, useTitles:true});
        prototypeValidators['form1'] = validator;
      </script>
    </form>
  </body>
</html>

posted @ 6/23/2007 7:47 AM by Bill Pierce

MonoRail - URL Rewriting and Persisting QueryString Parameters

In my last post I talked about how each of our customers identify themselves to our app via a CustomerId query string parameter.  Rather than give links to our customers with ?CustomerId=12345 sprinkled about, I thought it would be nice to take advantage of the built in URL rewriting capabilities of MonoRail.  My target URLs have the following form, https://my.product.com/customerId/controller/action.rails and this will get rewritten to https://my.product.com/controller/action.rails?CustomerId=customerId.  Turns out this is a very simple configuration change.  URL rewriting is handled by the routing service in MonoRail.  You can configure custom 'routes' by adding a subsection to the monorail config section in your web.config file.  You also need to add the routing HTTP module to your list of loaded modules.  Here is what I added to get my desired result (adapted from the Exesto routing configuration):

<routing>
  <rule>
    <pattern>/(?'customerId'\d+)/(?'controller'\w+)/(?'action'\w+)\.rails(\?(?'queryString'.*))?</pattern>
    <replace><![CDATA[ /${controller}/${action}.rails?CustomerId=${customerId}&${queryString} ]]></replace>
  </rule>
</routing>
<httpModules>
  <!-- The order these are listed is important -->
  <add name="routing" type="Castle.MonoRail.Framework.RoutingModule, Castle.MonoRail.Framework" />
  <add name="monorail" type="Castle.MonoRail.Framework.EngineContextModule, Castle.MonoRail.Framework" />
</httpModules>

A few things to note.  We aren't currently using Areas and this routing rule would conflict with the default routing.  Make sure you load the routing module before the monorail module or your custom routes may not work.  Happy day!  We get prettier URLs and we still uniquely identify each customer's site which means they see their custom UI and execute their custom business logic.  There is one small issue though.  Whenever we LinkTo, Redirect, or BeginFormTag, we will need to take the CustomerId and make sure it is injected in the right place in our URLs.  Ugh!  big pain, no thank you.  MonoRail to the rescue! 

The beauty of MonoRail is that it is composed of a number of independent services that can be replaced at will with custom implementations.  The difficult task is determining where is the best place to inject the custom functionality you desire.  In my previous post we implemented runtime views and layouts using a Filter.  Is this the only way we could have achieved it?  No, but it was probably the most logical and the way MonoRail was intended to be extended.  There are a number of ways I can extend MonoRail to ensure that the CustomerId querystring parameter is persisted from request to request.  I chose to make my extension to MonoRail's UrlBuilder.  The UrlBuilder is in charge of...building URLs :)  It allows you to pass in an area, controller, and action, and it will return a well formed URL to said resource.  This seemed like the most logical place to add something to a URL.  I derive from DefaultUrlBuilder and override InternalBuildUrl which is the method used to generate final URLs (I've submitted a patch to make this method virtual, should be in the trunk in the next few days).  I simply check to see if CustomerId is already on the QueryString.  If so, it is inserted into the proper place to generate a URL that will be recognized by the routing rule we implemented above.

namespace My.Product.Mvc
{
  using Castle.MonoRail.Framework;
  using Castle.MonoRail.Framework.Services;

  public class AppendCustomerIdUrlBuilder : DefaultUrlBuilder
  {
    protected override string InternalBuildUrl(string area, string controller, string action, string protocol, string port,
                                               string domain, string subdomain, string appVirtualDir, string extension,
                                               bool absolutePath, bool applySubdomain, string suffix)
    {
      if( !absolutePath )
      {
        string customerId = MonoRailHttpHandler.CurrentContext.Request.Params["CustomerId"];

        if( !string.IsNullOrEmpty(customerId) )
        {
          appVirtualDir = string.Concat(appVirtualDir, '/', customerId);
        }
      }

      return base.InternalBuildUrl(area, controller, action, protocol, port, domain, subdomain, appVirtualDir, 
        extension, absolutePath, applySubdomain, suffix);
    }
  }
}

Now, how do I instruct MonoRail to use my UrlBuilder instead of the DefaultUrlBuilder?  Once again, it is a simple configuration change.  Based on information from the MonoRail Configuration reference, its a piece of cake to slip in a custom service.  The configuration below goes in the MonoRail section of your web.config.  Using the well known id 'UrlBuilder' and the full type of my class, we are rocking and rolling.

<services>
  <service id="UrlBuilder" type="My.Product.Mvc.AppendCustomerIdUrlBuilder, My.Product.Core" />
</services>

posted @ 6/21/2007 10:29 AM by Bill Pierce

MonoRail - Runtime Views and Layouts with Filters

I've been on a bit of a MonoRail kick lately and thought I might share some gems.  In his recent post Hammett talks about, among other things, using a filter to change layouts at runtime.  He didn't elaborate so I thought I would share the way I've implemented his idea.  In our hosted environment we generally prefer each customer to have a separate host header.  For various reasons this isn't possible for some customers.  Instead, we identify them based on an internal id.  We key everything about the application off of this id.  We use this id to display a customized user interface and run custom logic on a per customer basis.  The way I am currently implementing the customized user interface is, as Hammett stated, with Filter. 

We grab the CustomerId from the query string and use that to determine if that particular customer has a custom view using a simple folder structure: Views -> CustomerId -> Controller -> View.brail.  If no custom view is found, we instead use a 'base' view that is stored in an identical structure Views -> Base -> Controller -> View.brail.  Pretty straight forward.  We do the same thing for layouts.  Decorate your base controller with an AfterAction attribute and you are all set.

namespace My.Product.Mvc
{
  using System.IO;
  using Castle.MonoRail.Framework;

  public class CustomViewFilter : IFilter
  {
    public const string BASE = "Base";
    public const string LAYOUTS = "Layouts";

    #region IFilter Members

    public bool Perform(ExecuteEnum exec, IRailsEngineContext context, Controller controller)
    {
      string customerId = context.Params["CustomerId"];
      return Perform(exec, context, controller, customerId);
    }

    #endregion

    public bool Perform(ExecuteEnum exec, IRailsEngineContext context, Controller controller, string customerId)
    {
      // Use the Base or Customer specific view
      string viewName = null;
      if( null != controller.SelectedViewName )
      {
        viewName = Path.Combine(BASE, controller.SelectedViewName);
        if( null != customerId )
        {
          string customerViewName = Path.Combine(customerId, controller.SelectedViewName);
          if( controller.HasTemplate(customerViewName) )
          {
            viewName = customerViewName;
          }
        }
      }
      controller.SelectedViewName = viewName;

      // Use the Base or Customer specific layout
      string layoutName = null;
      if( null != controller.LayoutName )
      {
        layoutName = Path.Combine(BASE, controller.LayoutName);
        if( null != customerId )
        {
          string customerLayoutName = Path.Combine(customerId, controller.LayoutName);
          string customerLayoutPath = Path.Combine(LAYOUTS, customerLayoutName);
          if (controller.HasTemplate(customerLayoutPath))
          {
            layoutName = customerLayoutName;
          }
        }
      }
      controller.LayoutName = layoutName;

      return true;
    }
  }
}

posted @ 6/21/2007 9:33 AM by Bill Pierce

My future in Racquetball

My back has been really killing me for the past few weeks.  I have a pinched nerve that I injured a few years ago. I was playing 4 times a week strenuously, while not being in the best of shape. A day came when I could barely stand up.  I went and had an MRI and multiple doctors told me that I shouldn't play the game anymore.

I slowly nursed myself back to playing shape and had some of the best games of my life, and was pretty pain free until again this year.  This time though I can walk fine, but anything other than lying down hurts.  It's not the doubled over in pain type of hurt, just the constant "pinch" all the way down my leg, into my back, down my arms, and in my neck.  My right leg gets most of the shooting pain.

It's really annoying and sometimes I cramp up just walking about.  Walking has also started to really aggrevate it, so trips to Disneyland are starting to get harder.  I don't have to take breaks because I'm tired, but because I have to strech.

It makes me feel like a weakling and it freaking sucks.  I hate laying about dormant, so I've taken up some less strenuous exercise like elliptical machines and swimming (although I am just starting to do those).  I also think I need to buckle down and get a physical therapist.

I think back to my roomate in college, Chris Odegard, and how he had crippling back and leg injuries that made it painful to walk (one time he couldn't even get on the lift at Vail - $80 go bye bye!).  He said that he worked with a physical therapist and now he's pretty pain free.  He's even playing some great racquetball, which gives me some hope.

I was talking the other day and I do think I'm done in outdoor racquetball.  I just think it's too hard on my body.  It's a great game, but I'm still hurting really bad from practicing 3 weeks ago.  I made it to the semi's at Nationals after playing for 2 years, so that's good enough :)  I think I might try doubles as the movement isn't as bad, but I've got to get my back healed to a point to where that can happen.  Not very happy about it.

posted @ 6/19/2007 8:23 PM by William C. Tilton

Getting in better shape

Over the past few days I've been working out on things other than racquetball, trying to keep my heart rate up around at least 140 (about 72% according to this).  During the day I can peak around 146, but I feel pretty tired (over a continuous 20-30 minute workout).  Tonight I was able to sustain 150 (78%) fairly easily for 30 minutes working up a good sweat on an elliptical.  Jackie pointed out that I was on a different machine, but I'm going more towards keep my heart rate up and going than what particular aerobic exercise I'm doing.

posted @ 6/19/2007 8:11 PM by William C. Tilton

Binsor the Friendly DSL

Oren posted quite a while ago on a little DSL for configuring Castle Windsor using Boo. He has creatively titled this DSL Binsor. I had previously used the Batch Registration facility because I did not want to maintain XML configuration for 75+ components.  Since I am revisiting the project now and updating to the trunk Rhino Tools I thought I would try out Binsor.  Below is the complete script I use to configure MonoRail with Windsor, configure logging, wire up the NHibernate Repository, load all of my MonoRail Controllers/ViewComponents, and all supporting components.  This script is derived from the Hibernating Forums binsor script and the source for the Batch Registration facility.

import System
import System.Reflection
import Castle.Facilities.Logging
import Castle.MonoRail.Framework
import Castle.MonoRail.WindsorExtension

Facility( "rails", RailsFacility)
Facility( "logging", LoggingFacility, loggingApi: "log4net", configFile: "My.Product.log4net")
Component("repository", IRepository, NHRepository)
Component("unitOfWorkFactory", IUnitOfWorkFactory, NHibernateUnitOfWorkFactory)

coreAsm = Assembly.Load("My.Product.Core")

for type in coreAsm.GetTypes():
  if typeof(Controller).IsAssignableFrom(type):
    Component(type.Name, type)
  elif typeof(ViewComponent).IsAssignableFrom(type):
    Component(type.Name, type)
  elif type.IsDefined(typeof(CastleComponentAttribute), false):
    compAttr = type.GetCustomAttributes(typeof(CastleComponentAttribute), false)[0] as CastleComponentAttribute
    Component(compAttr.Key, compAttr.Service, type, compAttr.Lifestyle)

posted @ 6/19/2007 7:28 AM by Bill Pierce

Nationals

I would be the Women's Open Champion if I didn't have to leave on Saturday and come home to work on Sunday. I am playing the best I have played all year and after beating Adrienne and Vivian, there was no one in the way from claiming the title.

I didn't play well against Brenda in the Qualifier, for that I was disappointed, I just didn't handle her serve well. There were some nerves but not too many.  I had a great time in Houston and I had friends that won their divisions, so I am happy for them.

 I want to take this opportunity to thank Randi for the continous support and love to get through the season. to my coach lorraine who took a gold and a silver. Congrats and thanks, to my fans, thanks for everything, I will be playing all the WPRO stops next year and national doubles and singles. I am dissapointed with Houston, but with the wins over viv and adrienne I know I am ready to move up and to keep improving my game.

I am going to work hard over the summer and play alot of outdoor. And do you want to know a secret??? come back on July 1st to find out!!!

posted @ 5/29/2007 7:00 AM by Kimi F.

Referrer Authentication with One Time Pads

*Disclaimer:  I am going to describe a symptom of a problem and provide a simple solution to address the symptom, not the problem :)

One of our products is a web based catalog engine that we host for our customers.  We provide our customers with an administration tool they can use to setup end-user accounts (username/password) so they control who can view their catalogs.  We also have a number of customers that integrate our catalog application into a broader offering of their own.  Our customers want to take care of the user management through their own systems and simply redirect end-users from their site to our hosted catalog engine.  The issue that arises in this case is when the our customer disables an end user account they want to prevent the end user from accessing our catalog application.  If the end user has bookmarked our catalog engine, they can bypass the customers site and continue using our catalog engine.

One solution that may have popped into your head was to check the HTTP_REFERRER property on the request and match it against a known list of valid referrers.  The problem with this approach is that HTTP_REFERRER can be very easily spoofed.  There are a number of ways to address this issue but we needed something that was simple, repeatable, and required as little technical knowledge on the customer end as possible.

My quick solution was to implement one time pad (we aren't encrypting anything but I think the concept is still applicable) authentication to validate that the user was coming to our catalog engine from a trusted source.  I'll show how to implement this solution using SQL Server but it can work with any relational database (you could even do it using a plain text file).

  1. Create a table to hold your pads.
    CREATE TABLE OneTimePad
    (
      Pad UNIQUEIDENTIFIER
    )
  2. Populate your table with pads.
    SET NOCOUNT ON
  3. DECLARE @i BIGINT
    SET @i=0

    TRUNCATE TABLE OneTimePad

    WHILE @i < 100000 BEGIN
      INSERT INTO OneTimePad VALUES(NEWID())
      SET @i = @i + 1
    END

  4. Send a copy of the pad table to the customer.
  5. The customer will then append a pad to the url we give them to invoke our catalog engine.  Here is a sample sproc to get the next pad:
    CREATE PROC GetNextPad
    AS
      SET NOCOUNT ON
      DECLARE @pad UNIQUEIDENTIFIER
      BEGIN TRAN
        SELECT TOP 1 @pad=Pad FROM OneTimePad;
        DELETE FROM OneTimePad WHERE Pad=@pad;
      COMMIT
      SELECT @pad;
    GO
  6. On our landing page, we check for the presence of the pad parameter.  If it's not present, we send them back to the customer site.  If the pad is invalid, we tell them to take a hike.  Here's the pseudo code:
    pad = Request.QueryString["pad"]
    if( null == pad ) redirect back to customer site
    recordsAffected = exec("DELETE FROM OneTimePad WHERE Pad=?", pad)
    if( 0 == recordsAffected ) die "We're unhackable biatch!"

Our site forces end-users to access us through our landing page.  We only have to validate them when they get redirected from a customer.  Once those steps are in place we have a poor mans referrer authentication that is fairly solid and easily repeatable for other customers/hosted products.  We have the option to generate a gajillion keys or setup an FTP based key exchange.  The only way to compromise the system is to brute force it (good luck with that) or to compromise the pad database.  If the latter occurs, simply regenerate and exchange new pads.

I'm counting on you the reader to poke holes in this proof of concept :)

posted @ 5/25/2007 11:25 AM by Bill Pierce

USAR Racquetball National Singles Event

This year looks to be a fun event.  This is the second year in a row that I haven't gone, after going for 3 years in a row.  My Mom and Dad were suprised that I wasn't down in Houston for the event, but such is life.  No enough money, too much of a pain with the kids, and my back has been killing me so I haven't practiced or even played in the last few weeks.

The event does now allow the pro's to play in their own "Team Qualifier" event.  Being a proponent of this, as it clarifies their involvment, I think it is should go pretty well.

RacquetballOnline.tv is also at the event this year.  We can all hope that their country funding makes it possible to get some real funding to finance the site and it's webivised events. 

Carrabba's also makes an appearance as a sponsor.  I freaking love Carrabba's so just thinking about how good the food is going to be at the tournament makes me want to be there.  I'm really interested to see how having them at the event helps with the hospitality.

The Hyatt also steps up as a sponsor this year.  I think they've sponsored the event since the beginning of the thing, and while I could be wrong, they're akin to the Promus' and current Choice Hotels' in this respect.

I wish all the participants luck and hope they have a great week.  If you're reading this, let me know how you did.

posted @ 5/24/2007 7:13 PM by William C. Tilton

Seperation of blogs

I'm starting to seperate each of my blogs into seperate sites.  MNP is mainly a sports related site, and as such the technical posts that I have been plopping up here just didn't fit, so I created a seperate blogging site for those.  I've also been wanting to bitch about current politics so I created a blog for that.  I also created a family blog site for more personal matters.

Having said that, only racquetball or sports related posts will appear here in the future.  Hee haw.  That is all...

posted @ 5/15/2007 10:24 PM by William C. Tilton

Did This Plan Backfire?

JATRAMMELL posted about the low numbers at the yearly National event.

While the overall numbers are barely going down, the number of top level players is reeeeally low. 14 and 5 players in the Open divisions?  Yikes.

Why is this concerning?

Because people who have played the game long enough to make the Open division just aren't playing anymore.  If Open players aren't playing anymore then the challenge for up and comers isn't there anymore either.  Think about it.  We all play the game to have fun, get some exercise and sociallize, but we all participate in something that is intristict to each sport: a challenge.

The goal of each sport is to win, to best your opponent(s) by being better.  What happens if you're the best?  It gets boring.  If you've "done it all", why would you continue (maybe if the money's good)?  It would get especially frustrating for some who because of the boredom start to lose to players that earlier they could beat easily.

Our sport also becomes made up of players that aren't "the best" anymore either.  With some of the best no longer playing the game, they are arguably being replaced with lower caliber players each year.  Not good.

I think the answer doesn't have to do with the tournament format, but more with the fact that organized racquetball is declining.  There are less and less people that play tournaments these days and it's showing at the national level.

Link to Meet and play forums

posted @ 5/15/2007 10:17 PM by William C. Tilton