Sunday, January 22, 2012

LetsBuy.com A Perfect Example of How Not to Run an Online Shopping Website

Today I am going to narrate a story, A real story.

In this story, lead role is played by Deep Shah (name not changed) and His Friends. Every story has good guys and the bad guys right, in this story the bad guys are LetsBuy.com (name not changed) as a company (nothing personal against anyone). There are some side hero's in the story as well, I will introduce them as and when they appear. I am all exited to tell the story to you guys, so here it goes!

The Plot:

There was a guy called Deep Shah - A Software engineer living in Pune.  He wanted to buy a new mobile, specs he wanted were:
  • Android OS
  • Dual core CPU
  • Minimum 4" Screen
  • 1GB RAM
  • Budget max Rs. 20K (approx  $400)
For a very long time none of the phones met all his criteria.  Samsung Galaxy R (around Rs. 25K), Samsung Galaxy S-II (around Rs. 28K) and Samsung Galaxy Note (around Rs. 33K) would match the technical specs but were totally out of his budget.

Then one day, one of his friend pointed out that prices of Samsung Galaxy R have fallen to about Rs. 21K.  He decided to go for it!

The Buy - The Good:

Just like any other middle class person, he decided to get the best deal (read that as cheapest deal) for his Samsung Galaxy R.  He checked out the prices at a few local stores, but the best deal he could find was around Rs. 22K.

The online price for Samsung Galaxy R was around Rs. 21K.  Deep Shah had ordered quite a few things (some of them expensive as well) online in foreign countries and they all were delivered just fine without any problems.  But in India, his online shopping experience was limited to books and some not so expensive stuff.  He really wanted to give Indian Online Shopping websites a go (actually he really wanted to save the 1000 bucks!).

Hence, he checked out few online shopping websites, that were selling The Samsung Galaxy R.  I am not going to mention other online shopping websites names (since this post is not about them).  He decided to order the phone from a website called LetsBuy.com who were selling the Samsung Galaxy R at Rs. 20990.

Why did he choose LetsBuy.com?
  • They had a decent web site
  • They had a call center where one could call for enquirers between 8 am to 9 pm, 7 days a week
  • They were giving away free branded accessories worth Rs. 1200 absolutely free
  • He had found a discount coupon for LetsBuy.com which would give him an additional Rs. 1000 off!
Obviously, the last two reasons were the most important reasons to choose LetsBuy.com, the phone was costing Rs. 19990 after all the discount!

OK so the choice of the website was made, now it was time to actually place an order.  The moment of choosing the payment mode had arrived.  There were mainly two options Cash on Delivery and Pay by Credit Card.

The choice was simple, it was Cash On Delivery, however, there was a catch, the discount coupon wont work for the Cash on Delivery payment mode.  Damn, if he choose Cash On Delivery the phone would cost 1000 bucks more.  You guys must have guessed his choice of Payment Mode by now, yes he choose Pay be Credit Card.  Unfortunately to save 1000 bucks he risked loosing Rs. 19990!

The order was placed on LetsBuy.com on 30th December 2011 a Friday -   Lets buy order number: LSB-757065 (actual order number).  LetsBuy.com claimed that they will delivery the phone in 2-4 business days.  Deep Shah was expecting the delivery latest by Thursday.  Now it was time to wait anxiously for the delivery.

The Confusion - The Bad:

He checked the order status on LetsBuy.com and found that that, the order was going to be dispatched in two parts, one was the actual phone and other was the accessories.  Over the weekend he saw that his order was partly dispatched from LetsBuy.com.  The phone was on its way!

By Monday (02/01/2012), LetsBuy.com had updated the shipment number and the courier company's name on the order.  The phone was being dispatched by a company called Aramex (name not changed), the shipment number was 6273338610 (actual shipment number).

Checking the current status on the shipment on Aramex.com, showed that shipment was on its way to Pune.  However, one thing caught his attention, the shipment was to be delivered in Pune - 411013, but, when Deep Shah had placed the order the address mentioned as Pune - 411016.

Hmm, how could the pin code be different.  He and His Friends smell something fishy. 

He decided to call up the courier company to find out whats wrong with the order.  The courier company Aramex was pretty prompt and accurate in their response.  He could talk to an executive within 30 seconds.  Deep Shah asked the executive to track the shipment 6273338610, to his surprise (read that as "shock"), executive informed that, the Order was in the name of Mr. Amer (name changed) and order was to be delivered in Magarpatta, Pune - 411013.

Clearly, something was messed up.  Initial guess about the problem with Deep Shah's order was:

Probably incorrect shipment number was updated against the order on LetsBuy.com

He asked the courier company executive to find any shipment against his phone number (the number that he had given while booking the order).  But unfortunately no shipment was found against his phone number.

Next, he decided to call LetsBuy.com call center to get some clarification.  This was the first time that Deep Shah would talk to LetsBuy.com call center executive.

He had to wait a full 7 minutes before he could actually speak to someone at LetsBuy.com.

Deep Shah explained the situation with his order and asked for an explanation.  The executive calmly said that may be an incorrect shipment number was updated for his order (which was his guess anyways).  Executive requested Deep Shah to wait for 24-48 hrs and he will get this error resolved.  Executive registered a complaint (no: cc120139286 - actual complaint number).  This was on 02/01/2012

The Followup - The Ugly:

Next day (Tuesday 03/01/2012 - i.e. after 24 hrs), he logged on to LetsBuy.com to see if the shipment number was updated.  But, there was no change in the shipment number.  He decided to wait for one more day. 

Next day (Wednesday - 04/01/2012), ditto, no change in the order information.

He decided to call LetsBuy.com again to find out whats going on for his complaint.  Again, it was a long wait for 9 minutes before which he could speak to someone at LetsBuy.com.

Deep Shah had to repeat the entire story again to this new person.  Executive informed that they were working on Deep Shah complaint and he has no update on the status of the complaint.  Executive requested Deep Shah to wait for another 24 hrs.  On this day, Deep Shah received the free accessories (not the phone).

Next day (Thursday - 05/01/2012), there was an unpleasant change on the order status, the Order status showing as Delivered on LetsBuy.com.  That freaked out Deep Shah a bit.

He tracked the shipment no: 6273338610 on Aramex.com website.  Turned out that it was actually delivered to Mr. Amer.  But no, Deep Shah had not received the phone yet.
Shipment Delivery to Mr. Amer
He called LetsBuy.com, after a long wait for 8 minutes, he could speak to someone at LetsBuy.com.

He had to explain the entire story again (which was very frustrating).  You must have guessed the result of this conversation by now, executive asked Deep Shah to wait for another 24 hrs as they had no update on his complaint/order.  Executive even assured him that by the next day, in most likelihood Deep Shah should receive the product.

Next day (Friday - 06/01/2012) nothing happened.  Following up with LetsBuy.com was frustrating and pointless.  Every time, Deep Shah had to wait for long durations and then explain someone the same problem all over again and get the same response.

LetsBuy.com executives would not give their direct contact numbers or their email address.  This means
  • Long wait before one could speak to a LetsBuy.com executive
  • Explaining the situation all over again (to different executives) and eventually get the same response - Please wait for 24 hrs.
Wait for 24hrs and do what?  Expect some miracle?

On Sunday - 08/01/2012, i.e. Full 10 days after placing the order, Deep Shah still didn't have any trace of his phone.

He had received the free accessories, as one of my friend keeps saying,

Its like giving an hungry dog a rubber bone!  

Deep Shah called up LetsBuy.com again and this time demanded to speak to some manager.  He got to speak with Mr. Laxman Patil (name changed) a supervisor at LetsBuy.com.  He seemed like a nice guy, heard Deep Shah out, understood the situation and promised to look into the matter himself.  By this time all Deep Shah wanted was a regular feedback on his order.

Being a software engineer, he understands that all systems are pron to programming/human bugs/errors.  But customers should be given regular feedback on what action was taken to rectify the mistake.  Even after contacting LetsBuy.com, like 10 times, LetsBuy.com didn't have enough courtesy to call Deep Shah and update him with the complaint status.

BTW the order status on LetsBuy.com was Delivered, they didn't bother to change it, even after they agreed that it not yet delivered.
Order Status is Delivered Even though no phone was delivered
Next day (Monday - 09/01/2012), no news from LetsBuy.com, no news from Mr. Laxman Patil.  During this period Deep Shah wrote numerous mails on customercare@letsbuy.com but LetsBuy.com didn't respond to even one.

During these days, Deep Shah and His Friends tried our different (random) tracking numbers, which were around the tracking number that was given to Deep Shah.  They found quite a few tracking numbers that had funny shipment history.  For e.g. Tracking Number 6273338621 was delivered twice once in Panji, India and once in Bombay India.

Shipment Delivered Twice
What did this signify?  Does this mean Aramex was reusing shipment numbers?  

We called up Aramex to ask whether they were reusing shipment number?  Of course they said shipment numbers are unique.  They cannot be duplicate.

Deep Shah and his friends could find multiple instances where there were two deliveries made on one shipment number.  If you notice the tracking history of Deep Shah's shipment number you can see, even that one has two shipments moving.
  • One shipment arrived in Pune on 31/12/2011 at about 1845 hrs and went on hold.  
  • Other shipment started from Banglore on 02/01/2012 and was delivered on 05/01/2012 to Mr. Amer
Notice two shipments moving on one shipment number
In this shipment, notice that, there are two products involved but only one delivery was made.  While in all other shipments we noticed that two products were moving on the same shipment number but two deliveries were also made.

By this time, Deep Shah and His Friends were sure that his shipment was lying in Aramex Pune office but was never delivered.

What was so special about this shipment?  Why others got delivered but this one was not delivered?

The interesting thing to notice about all other shipments with duplicate shipment numbers was that, they were to be delivered in different cities.  for e.g. in the image shown above, one product was to be delivered in Panji Goa and other one in Bombay.  But, in Deep Shah's case both the shipments were to be delivered in Pune.

This was the turning point.  After some motivation from Deep Shah's Friends, they decided to visit Aramex Pune office and figure out if their theory was correct.

On Wednesday - 11/01/2012, There was still no updates from LetsBuy.com.  Even after giving numerous calls to LetsBuy.com no one would every get back to give any update.

Deep Shah would call LetsBuy.com and insists to speak to Mr. Laxman Patil, he would have to wait for full 15-20 minutes, eventually Mr. Laxman Patil would inform that, he has escalated the case to higher authorities and action will be taken.  It was too late and too little and very very frustrating. 

Deep Shah and His Friends visited the Aramex office in the evening and explained them the situation.  Initially they had tough time explaining them that two shipments were moving on one shipment number.  If they looked up the shipment number in their system it would always bring up details of Mr. Amer's shipment.  As there cannot be two shipments with same shipment number.  Entire logistics business is based on this assumption. 

Once a logistics expert (who had around 15 years of experience in Logistics) told me that,

We cannot have duplicate shipment number being generated in production, this would have catastrophic effects.

Now, I truly understand what he meant by that!

Anyways, In Aramex Pune office one guy (A very good guy) did agree that, two shipments were moving on one shipment number.  He and his team manually checked all the shipments that were present in his warehouse.

Guess what, they did find a box that was shipped by LetsBuy.com and was with the same shipment number i.e. 6273338610.  One very smart person at Aremex Pune office had kept this shipment aside since he saw two similar shipments with same shipment number had landed in his warehouse.

It seemed like the mystery was getting resolved, it was clear that the box had the phone for Deep Shah, but, Aramex would not deliver it to Deep Shah since, in their system, this shipment belonged to Mr. Amer.  Funny part was, the shipment was already delivered to Mr. Amer.

Aramex guys requested Deep Shah to wait for one last day so that they could get a confirmation from LetsBuy.com about the shipment and delivery it to him. 

Next day, Thursday - 12/01/2012 - Deep Shah called up LetsBuy.com to inform them about what he had found out, he had also written an email to inform about this new development.

Again as usual they asked Deep Shah to wait for 24-48 hrs.  LetsBuy.com call center is like an IVR system which is programmed to listen to what customer has to say and always respond by saying we will get back to you in 24-48 hrs and never bother call the customer back.  Worst part is they will ask whether they can help with anything else?, what a joke!

In the evening at about 1730 hrs, the smart guy from Aramex Pune office called up Deep Shah and asked him to come and collect his phone.  Finally a sign of relief, Deep Shah did get his phone after 14 days of placing his order!  Aramex Pune office folks actually managed to resolve the issue within 24 hrs as promised by them.  They really were the people who saved the day in the end.

Out of curiosity, Deep Shah the smart guy at Aramex, Why duplicate shipment numbers are getting generated?

Turned out, a range of shipment numbers have been allotted to LetsBuy.com and they are not supposed to repeat them.  But, because of a bug in LetsBuy.com's system, same shipment numbers were getting used for two different shipments.

Well, I can understand that mistakes do occur when you are running a business, but the quality of service is judged by how well you handle those erroneous cases.  Letsbuy.com failed miserably in handling this case.  

On a scale of 1 to 5, I would rate my shopping experience with LetsBuy.com at -5.  I hope not every customer is treated like this at LetsBuy.com else its just a matter of time before which they perish!

What Should have been done:
  • Customers should not suffer because of some goof up in the system
  • Customers should always be keep informed about the status of their complaint
  • Customers should not be waiting for 7-15 min before which they can speak to a customer care executive
  • Customers should not be speaking to different executives every time they call. 
I am sure LetsBuy.com knows much better how to run an online shopping website.  However, things that I have pointed out are just common sense items which should not have been ignored.

End Result:

Deep Shah and His Friends promised themselves never to buy any thing from LetsBuy.com and hopefully people who read this post would do the same. 

Moral of the story:
  • Never judge a website by the amount of discount they are offering on a product
  • Choose the one that has a better reputation and better and responsive customer care
  • Always always always opt for Cash On Delivery payment method
Standard Disclaimer: 

Every incident mentioned in this story is real.  All order numbers and shipment number are real order/shipment numbers.

Saturday, December 31, 2011

NHibernate throws InvalidCastException in DEBUG mode for entities with composite keys

Recently we faced a very weird issue with NHibernate.  The issue was, on one developer's machine, when we ran an Integration test to fetch an entity (using its primary key), NHibernate threw an InvalidCastException exception.
The issue was *not* reproducible on any other developer's machine.  This got me thinking, there must be some issue with the mappings which is causing NHibernate to throw the exception.  The developer must have made some local changes to the mapping files, that is causing the exception.

Investigation:

I tried various things to figure out what was causing the problem.  Here is the list of things that I tried.

Check mapping files for modifications:

I checked and rechecked the mapping files for any local modifications, but, No, there was no local modification.  I even checked-out all the mapping files just to be sure that there was no modification.  But still no luck, the issue was reproducible on her machine and not on any other machine.

Tried to reproduce the issue on my machine by connecting to other developers Database:

After the first failed attempt, next thought that crossed my mind was, may be, there was something wrong with entity data which is causing the exception.  I decided to run the same test on my machine by connecting to other developers database.

Surprisingly, I was still not able to reproduce the issue.  This was totally weird.  I was 99% positive that, issue would get reproduced once I connect to the order developers database.

I was running out of options.  How do proceed further?  What should be the next step?

Stick to basics - Debug with Elimination:

I was back to the drawing board.  Decided to use Elimination to narrow down the issue. The question that was bothering me was, Whats so special about the entity we are trying to load?

The entity we were trying to load was called EmpDept, it represents the Employee Department information (actual names of the entities have been changed).  So what was so special about this table?

This table was a legacy table, it did not have a primitive primary key, it had a composite key made of UserID and DeptID.

So what?  A lot of legacy databases have composite keys, NHibernate works well when it comes to mapping the composite keys, in fact, NHibernate has no problems loading the same entity on my machine!

I decided to, removed all other mapped properties and just kept the mappings for the composite key and try to fetch the entity.  This time, it did fetch the entity without any problems on the other developers machine!

We were starting to get somewhere now!

I started adding back the mappings to find out which one was causing the issue.  Finally, we did find the minimal possible mapping that would reproduce the issue.

The Cause:

We deduced that, the issue occurs when the following conditions are satisfied
  • Entity is mapped with composite primary key
  • Entity has a one-to-many relationship with other entity 
  • The one-to-many relationship is not based on the composite primary key, instead its with property-ref 
  • And the data type of property-ref is different from the id property 
Wow!  I know, those are too many conditions to be true at one time!

Let's look at the minimal mapping file that reproduced the issue
What do we have here?  We have a very simple mapping between two entities.
  • Entity EmpDept is mapped to a table called EmpDepts
  • EmpDept uses a composite primary key to class EmpDeptIdentifier
  • The composite primary key consists of UserID and DeptID
  • EmpDept entity as another property called Email
  • There is a one-to-many relationship between EmpDept and Task entity i.e. One EmpDept can have Many Tasks
  • Note that the relationship is not based on the composite primary key
  • The relationship is based on a non identifier property called Email
  • The data type of the Email property is string while the data type of the composite primary key is EmpDeptIdentifier 
By now, it must be clear that all of the required conditions for NHibernate to throw an exception have been satisfied, because of this NHibernate throws the InvalidCastException.

So far we had figured out, what conditions were required for NHibernate to throw the exception.  However the real mystery was, Why was the exception occurring only on one developers machine?  Why not on other developers machines?

The Enlightenment:

Our curiosity levels were at all time high!  We decided to debug the NHibernate code to figure out why was exact same code working perfectly fine on one machine and failing on other.

After some intense NHibernate code debugging we found the NHibernate code that was throwing the exception.
Notice the line that throws the InvalidCastException in the above code?  This is where the exception occurs. 

The above method is called to build a string that will be used for logging.  We traced back the call to this method, it was getting called from the MessageHelper.InfoString method, which in-turn was getting called from the LoadContexts.LocateLoadingCollection method.

We now knew the place from where the exception was thrown, but we still didn't know why it was thrown only on one machine. 

Looking through the NHibernate code we realized that, the method MessageHelper.InfoString is only called if NHibernate is running with DEBUG log level.

That ladies and gentlemen, was the "Aha Moment!" for us.  This was the missing piece of the puzzle.   The developer on whose machine the test was failing was running NHibernate at log level DEBUG, while I was running the test at log level INFO.  Because of this the method MessageHelper.InfoString was never invoked on my machine and thus no exception!

We Googled a little and found that there is an official bug reported for this scenario.  

Eventually it turned out that, what we initially though as a big issue was really a non issue, since NHibernate will not be configured in DEBUG mode 99% of the time (because it logs hell lot of information).  The issue we were facing is very unlikely in real systems.  Although it was not such a big issue after all, this experience taught us quite a few things about NHibernate!

Sunday, November 13, 2011

Integrating Spring.NET with ASMX WebServices

In one of the previous post, we saw how easily we can Enable Dependency Injection for Web Forms Web Pages and User Controls.  In this post we will cover the last topic in the Dependency Injection series i.e. Enabling Dependency injection in ASMX WebServices using Spring.NET.

Its not at all difficult to Enable Dependency Injection in ASMX WebServices.  Lets look at the steps we will need to it
  • Configure the Spring Context in web.config
  • Add the Spring WebSupportModule Module to the list of httpModules
  • Configure the WebServiceHandlerFactory to intercept any path that matches the pattern *.asmx
  • Configure the WebService class in spring config file with its dependencies
Let's look at each step in a little more detail.

Step - 1 - Configure the spring context in web.config

First we need to add spring config section handler in the configSections.  The updated web.config looks like
Next we need to add the spring config section in web.config. This section will inform Spring.NET as to where should it look for its configuration file. Add the following section to web.config
Nothing special about the above piece of configuration. We are informing Spring.NET that its configuration file is located in ~/Config/ directory and its called webservice.xml.

Step - 2 - We need to add the Spring WebSupportModule module to the list of httpModules

In this step, we will need to add the WebSupportModule to the list of httpModules in the web.config.  This is how the updated web.config looks like
Step - 3 - Configure the WebServiceHandlerFactory to intercept any path that matches the pattern *.asmx

Again, all we need to do here is add an Handler in the httpHandlers section in web.config. Update web.config looks like
Step - 4 - Configure the WebService class in spring config file with its dependencies

We are almost there. All that is left now is to configure the WebService class in the Spring.NET configuration file webservice.xml.

Let's say that we want to develop a HelloWorld webservice, that has one method called GreetUser.  This method takes in the user name as argument.  We will inject the greeting to be used using Spring.NET.

The code of the HelloWorld webservice looks like


Nothing to explain here, all we are doing is prepending the Greeting Property to the userName passed and returning the value as the result.

Notice that this HelloWorldService class is a POCO and there is nothing web service specific to it.

The spring configuration that will inject the Greeting into the HelloWorldService looks like
Notice that, we are configuring the implementation of WebService with the ID HelloWorldServiceImpl.  However, the actual WebService is exposed via Spring.NET.  The Spring.Web.Services.WebServiceExporter acts as a proxy over the actual WebService implementation.

All set!

Lets run the server and browser the URL which would look like http://localhost:<your-port-number>/HelloWorldService.asmx?op=GreetUser.  This should open up a page which looks like this
Page which will let us invoke the HelloWroldService.GreeUser WebService
This is the page from which we could invoke the HelloWorldService.GreetUser WebService.

Let's type in Git Shah in the user name field and click Invoke.  Here is what we get
As you can see, the greeting message Good Morning was injected in the HelloWorldServiceImpl class via Spring.NET.

That's all folks, we have successfully Integrated Spring.NET with ASMX WebServices!

Sunday, November 6, 2011

Making operator precidence more explicit with NHibernate Linq Provider

Recently, while writing one of the NHibernate queries, using the NHibernate LINQ provider we faced a very interesting problem.

The issue was the NHibernate LINQ provider was not adding appropriate parenthesis to make the operator precedence more explicit.

The query was simple enough, we wanted to get a list of records based on certain condition. Let's say, for the sake of this post, consider that there is an employees table with ID, Name and Salary columns. The DDL to create the employees tables on SQLServer looks like
NHibernate class against which this table is mapped is called Employee. The Employee class and its mapping file looks like
As you can see there is nothing fancy about the table or the mapping.

Let's talk a bit about the query we want to fire against the employees table.  We want to get list of employees whose name equals "Git" OR whose salary is between 1000 and 10000.

The SQL that would do the job for us would look like:

Again nothing remotely fancy about the SQL.

Let's try and write the same query using, NHibernate LINQ provider and lets look at the generated SQL.  The NHibernate LINQ query to get similar results would look like:
The where condition is the exact replica of the SQL where condition that we had seen earlier.  Only difference this time around is, we are using the LINQ syntax.

So far so good, the problem starts when we look at the SQL that is generated. The simplified version of the SQL generated from the above LINQ query looks like

I have removed all the named parameters that NHibernate adds, but essentially the query looks like the one shown above.

Whats wrong with the query? 

Notice that there are no parenthesis to enforce the operator precedence!  Because of this, it might get confusing to identify the order in which the operators will be process.

Consider a case when you have a complex query with many conditions and if proper parenthisis are not applied then it could get confusing.

I tried various permution and combination to force the NHibernate LINQ provider to spitout the parenthesis correctly, however I was not successful in doing so.

Finally, I decided to switch to the QueryOver API provided by NHibernate.  QueryOver API is a Fluent wrapper over the NHibernate Criteria API.  Using the QueryOver API the above code would look like

As you can see the nothing much has changed.  The only changes are, .Query() call has been changed to .QueryOver() and instead of .ToList() we have to call .List().

Let's look at the generated SQL Query:
As you can see, it correctly adds the parenthesis to make the operator precedence more explicit!

Friday, October 28, 2011

Enabling Dependency Injection In Web Forms Pages and User Controls using Spring.NET

In one of the previous post, I mentioned, How MVC3 and Web Forms can exist side by side in one project.  We also saw, how we could Enable Dependency Injection using Spring.NET in an MVC3 Application.

But, What about the old Web Form pages and user controls?  Can we Enable Dependency Injection in them, so that we can create loosely coupled code?

Surely there is a way of doing this using Spring.NET.  In this post we will carry on from where we left and we will try to enable Dependency Injection even for Web Pages and User Controls.  Before moving any further, if you have not already seen my previous post of integrating Spring.NET with MVC3 Application, now is a good time to see it.

Without wasting any more time, let's see how we can enable Dependency Injection in Web Forms and User Controls using Spring.NET

How Do they Do it?

For sake of this post, let's say we have a web page called Default.aspx under the Pages directory.  The structure of the project looks somewhat like this

The project structure with Default.aspx
Our task is to inject the AccountService into the Default.aspx page.  As mentioned in the previous post AccountService is a class that was already configured in Spring.NET, it has one method UserCount and we are going to show the user count on the Default.aspx page.

The steps to enabled dependency injection in web-forms web pages using Spring.NET are as follows:
  • Add HttpHandler, called Spring.Web.Support.PageHandlerFactory for path *.aspx
  • Make code changes to Default.aspx to fetch the UserCount from AccountService
  • Configure the dependencies of Default.aspx in web.xml (web.xml is a spring config file which we created in the previous post)
Let look at each step in more detail.

Step - 1 - Add HttpHandler Spring.Web.Support.PageHandlerFactory for path *.aspx

This step is pretty straight forward all we need to do is, Add an HttpHandler, called Spring.Web.Support.PageHandlerFactory.  We need to configure it against the path *.aspx.  This is required so that, Spring.NET gets an opportunity to perform Dependency Injection when a request comes for any web-forms web page. 

We need to add the handler to the <httpHandlers> tag in the web.config.  Updated web.config looks like

Step - 2 - Make code changes to Default.aspx to fetch the UserCount from AccountService

Lets look at the Default.aspx page
As you can see the html code of Default.aspx is very simple. It just has a label called userCount which will hold the value of number of users in the system.

We will get the value of userCount from AccoutService. Let's look at the code of Default.aspx.cs file The code of Default.aspx.cs has no surprises, it has a property AccoutService. We will plan to injet an implementation of AccoutService using Spring.NET.  In the Page_Load method, we simply set the userCount label with the value returned by the UserCount method of AccoutService.

The only question left to answer is, how do we inject the AccoutService into the Default.aspx.cs. 

Step - 3 - Configure the dependencies of Page Default.aspx in web.xml


For configuring the AccoutService dependency in Default.aspx we have to add the following object declaration in web.xml
Notice that we simply have to add the declaration of Default.aspx with proper path in web.xml. Since, Default.aspx is located in the Pages directory, we have to refer it as ~/Pages/Default.aspx. We have to add all the dependencies for the page, just like how we do it for other Spring.NET objects.

All set, lets test our setup and browser the page Default.aspx to see the result.
Enabled Dependency Injection in web.forms using Spring.NET
As you can see, we are able to see the user count value on the page.  We have successfully Enabled Dependency Injection in Web-Forms Web Pages.

Lets quickly see how we can enable dependency injection in User Controls.  Steps to do that are as follows:
  • Create a user control called UserCount.ascx that invokes AccountService to get the user count
  • Update the Default.aspx to use the UserCount.ascx user control
  • Configure the UserCount.ascx in web.xml
Step - 1 - Create a user control called UserCount.ascx that invokes AccountService to get the user count 

We are going to create a very simple user control.  Let's call it UserCont.ascx.  This user control will simply fetch the user count using the AccountService and show it on the UI.
The code of UserCount.ascx is very simillar to what we have already seen in Default.aspx.  We are setting the value of userCount label by invoking the UserCount() method of AccountService instance.

Notice that, we are not instantiating AccountService anywhere in the user control. We will inject it using Spring.NET.  Before we look at, how exactly we do that lets update the Default.aspx to make use of the UserCount.ascx user control.

Step - 2 - Update the Default.aspx to use the UserCount.ascx user control

Let look at the updated Default.aspx
Nothing very alarming here. We simply are including the user control UserCount.ascx and showing it on the html.

Step - 3 - Configure the UserCount.ascx in web.xml

The final step is to configure the UserCount.ascx in web.xml.  Here is how we do it.
Notice that we registered the UserCount.ascx in Spring.NET configuration file. We simply have to specify the complete path of the UserCount.ascx.  Notice that we didn't have to change the configuration for Default.aspx at all.  Spring.NET is smart enought to inject the correct instance of UserCount.ascx in Default.aspx.

Another important thing to notice is that we have to add abstract="true" to the declaration of UserCount.ascx. 

All set, let's see the setup in action


Enabled Dependency Injection in user controls using Spring.NET
As we can see, we see two lines on the page showing the UserCount, first one is getting the user count directly from Default.aspx web page, while the second line is coming from the UserCount.ascx user control.

Mission Accomplished!

Saturday, October 22, 2011

2300 Miles US Road Trip - Part - 2

As mentioned in the previous post, we recently took a vacation in the US.  The previous post is about, my experiences on the trip in the first week.  In this post, I plan to share my experiences on the trip for the second week.

On a nice Sunday morning we decided to start our road trip. 

Destination Niagara:

We started our road trip from Chicago towards Niagara.  The distance of about 570 miles.  We were 4 adults and one kid traveling in an Honda Odyssey.  The drive took around 10 hours.  On the way we saw some very beautiful landscapes.  Here are a few images
Giant White cloud

Moon in all its glory

Metal Bridge on the way
Finally, at about 2030 hrs we reached our hotel at Niagara Falls.  I was really exited to finally see the Niagara Falls, I had read about them seen them on Discovery Channel, but as they say
Seeing is believing!
We decided to freshen up and grab a quick dinner and go straight to the falls to enjoy the night view of the falls.  I could hear the falls when we were at a distance of 0.5 miles (approx), simply thinking about the force of the falls was making me even more curious and exited.

When we reached the falls, I could not believe my eyes!  The falls were Beautiful, Gigantic, Fast and I don't have enough adjectives to describe them.  During the night, the falls are illuminated with lights of different color.  The lights, along with the mist created by the falls, make falls an amazing site to see.  Here are a few images
Fast moving falls along with very powerful floodlights

The lights keep changing their color which makes the scene even more beautiful.


On the other side where you see a tower like structure is Canada.  The two friendly countries are seperated by one bridge of around 0.2 miles.

The Bridge That connects US and Canada

The side from where the lights are flashed is Canada

The big tower on the Canadian side is a revolving hotel
After spending quite some time at the falls, we decided to head back to the hotel so that we can catchup on some sleep, the next day was going to be a long day

The next day, we start on a mission to explore Niagara Falls.  We decided to see a documentary on the history and mystery of Niagara Falls.  It was quite an interesting movie, did you know that, One Ms. Annie Edson Taylor, locked herself and her pet cat in a barrel and fell over the Niagara Falls and survived the fall! The movie was well scripted and was a fun watch!

Next we took a ride on the Maid of the Mist.  Its basically a boat ride that takes you very near the falls so that you can enjoy the view of the falls from its basin.

The Maid of the Mist boat that takes you near the fall

The American Falls And Bridal Veil Falls

The Horseshoe Falls

The Horseshoe Falls
 The boat ride was fun not only because we got to enjoy the beauty of the falls from very near but also because of hundreads of seagulls were flying around the falls. The entire landscape was really beautiful!
Seagulls flying around the falls
Next adventure was to go as near the fall as possible.  This time, a walk in the Cave of the Winds.

The Americans have build a wooden platform, just about 3 meters away from the falls, once you are there, you are bound to get completely drenched.  We experienced the force of falls pounding on top of our heads even when we were 3 meters away!

Cave of the Winds - The wooden platform 3 meters from the falls


Nearest point - You can't go any closer to the falls.  The force of falls was enormous.
As you can see from the images there is no way one can get out dry even with a raincoat on.  It was total fun!

We decided to spend the evening at the falls and enjoy its beauty, did a nature trail around the falls, overall had a fun filled day.  Here are some evening snaps of the Niagara Falls.


You can even see the dark spots on the moon

Destination Virginia Beach:

Next day, we decided to continue our trip.  Today's destination was Virginia Beach.  The distance of Virginia Beach from Niagara Falls was about 640 miles.  The journey took around 12 hours.

Our Hotel room had an awesome view.  The hotel was right in front of the beach.  There was nothing in between the hotel room and the beach!  We could see the beach from our hotel room terrace.  It was an amazing site!
Snap click from the hotel terrace
We could hear the waves from our room, the feeling was fabulous!  Next morning, I woke up early so that I could click some snaps of the sunrise 
Beautiful dawn at Sea
The sunrise and the reflection of sun in the ocean
Watched people feeding the seagulls, cycling at the beach, we even saw a few dolphins

The lady feeding the Seagulls

People cycling by the beach side

The small black spots that you see, are dolphins
I was pretty interested in doing some adventure activities at the beach, one activity that I wanted to do since a long time was Parasailing, we found a place and went for it.  The best part of Parasailing activity was when they dip you into the ocean!

Getting our feet wet while parasailing


Once we were back on solid ground, I saw my second love

Nice and Shining Harley Davidson
Yes, Harley Davidson, I had an opportunity to ride this bike once and from there on, I have fallen in love with it!

Destination Washington D.C.:



On the same day at about 1700 hrs we started our journey towards Washington D.C.  A journey of about 230 miles took us around 5 hours (caught in a jam on our way).

Next day we had a big list of places to visit.  We started early we saw the Capitol Building, White House, Lincoln Memorial, World war II Memorial, Washington Monument and finally the Air and Space Museum.

All these places are pretty close to each other.  One can easily walk and visit them.  But at the end of the day, I felt like I had no legs, I was dead tired.
The Capitol Building

The White House

Lincoln Memorial

Big Statue of Abraham Lincoln in the Lincoln Memorial

World War - II Memorial

Washington Monument


Air and Space Museum
Out of all these places, I liked the Capitol building and Air and Space Museum.

End of Journey:

Could not believe that it was already time to head home.  After a week of fantastic trip and wonderful memories it was time we start our journey towards Chicago.  A journey of about 750 miles took us around 13 hours.  On the way back, we also got a ticket for not wearing seat belts!

Had lots of fun with some very different/beautiful experiences (one of the "different" experience on the way back was, I lost my checked-in bag!)

Overall it was a fantastic and memorable trip!

Sunday, October 9, 2011

2300 Miles US Road Trip - Part - 1

Recently me and my family had an opportunity to visit the US for two weeks. I had some official work for about 4 days. We had planned a vacation for the rest of the time. Naturally, I wanted to visit lots of places, do lots of stuff when I was in the US. Some of the top places I wanted to visit were Niagara Falls, The White House, Virginia Beach, Pennsylvania, Florida, Yellowstone National Park, Hoover Dam, Las Vegas, The Grand Canyon, Sears Tower (Willis Tower) etc.

The list was endless and I knew we cannot cover all these places in just seven days. We had to decide on places that were practically possible and onces that I wanted to visit the most. We decided to do a road trip to some of the most appealing places (read that as places that were practically possible :)). We ended up doing a 2300 miles fantastic road trip, here is a post that summarizes my experiences on the entire trip and things that I loved the most.

Our journey started from the Pune airport.  We were supposed to fly from Pune to Delhi to Chicago.  We were visiting the Delhi Airport for the first, we had approximately 5 hours between flights, I thought that will be a good time to see the Delhi Airport.  I had heard lots of good things about it and boy, I was in for a surprise.

The Delhi Airport is one of the best International Airport that I have ever been to.  By the way, I have been to a lot of international airports (Dubai, Bharain, Addis Ababa, Israel, Frankfurt, Paris, Berlin, Zurich, Chicago, Minneapolis, Amsterdam etc.) and I can be sure that, this one was one of the best.

There were things to do, places to visit, shops to be explored, right at the Airport itself.  There are huge corridors, walkways, benches with palm trees around them, tint of indian culture etc.
Benches with palm trees around them

Huge corridors, walkways

Hand postures representing a dance form called Kathak
Out of all the shops at the Airport one that appealed the most to me had a healing pool in it.  Its like a small pool which has water till your ankles, people are supposed to remove their footwear and walk inside the pool.  The tiles in the pool would pressurize certain areas on your sole which gives you a very refreshing feeling.  This science is called Acupressure.  I did try it and felt totally incredible, felt really energized.

The healing pool with lots of bells hanging

As you can see people could walk in the pool and get rejuvenated
In the same shop there was live entertainment going on.

Person on left is playing flute and the other guy is playing tabla
The person with a long bamboo stick is playing a musical instrument called Flute and the other guy is playing a traditional Indian instrument called Tabla.  The sound of these instruments is very soothing and relaxing.

All around the Airport, there are huge beautiful metal sculptures which depict Indian culture

The Sculpture of lord Shiva
Delhi Airport had a western look as well.  There were recliner chairs with charging pods in the chair itself.  Nice, Shiny Mercedes was also lying around at the airport.  Over all it was a surprising experience.
Mercedes at the Delhi Airport

Next stop Chicago:

At Chicago on Monday - Labor Day - morning we visited a Swami Narayan temple near by.  The temple had a rich white facade with lush green lawn and blue fountains.  Under the clear blue sky with sparse white cloud cover it looked really beautiful!

The Swami Narayan Temple with white facade and lush green lawns

Blue colored fountains
Next stop Minneapolis:

As I mentioned earlier I had 4 days of official work.  I had to leave for Minneapolis on Monday.  But my trip does not stop here.  Even when I was at Minneapolis, my friends at work took me to some very nice restaurants in the evenings.
Pat sitting on the left hand side and Paul on the right


But by far the single biggest attraction of my stay at Minneapolis was the Base ball game!  My friends at Minneapolis had arranged tickets for a Base Ball game!

The game was between the home team i.e. Twins and Chicago White Sox.  Although the home team was not having a great phase they did win this game!  We had a very good view, our seats were right behind the batter, I could click some very good snaps



The road to the office was scenic, our office was around an artificial lake because of this the entire area had very good green cover with beautiful flowers and lovely trees!

Path way to the office


One evening one of my friend took me to the Mall of America!  Its supposed to be the second largest mall in the world and boy it was big!  There were hundreads of shops in fact it was so big that they had a mini amuzement part right inside the mall!  I did sit in one of the roller coster which looked the most scary roller coster it had a drop of around 93 degrees!

Back to Chicago:

After fishing my work in Minneapolis, I came back to Chicago on Saturday morning, we decided to visit Chicago down town in the evening.  Chicago downtown is just like any other city with lots of big buildings and beautiful lake near by.

We visited the Cloud Gate, Buckingham Fountain, Sears Tower, Navy Pier and oh yes, saw the fireworks at Navy Pier

The Cloud Gate is like a giant silver bean, it was quite a popular spot, we saw at least 6-7 newly wed couples near it.
The Cloud Gate





Snaps from the Buckingham Fountain, sears tower and navy pears
Buckingham Fountain


View from the Sears Tower



Fireworks at Navy Pier


At Sears Tower, there is glass compartment which is suspended, which means there is nothing below it - The Sky Deck!  You are standing on glass 110 stories high with nothing below you, Scary!

While heading home we even saw a opera it was quite interesting actually!
By this time one week had already passed.  I had lot of fun and some very first experiences in this memorable one week.

Next day we were supposed to leave for our road trip.  In my next post I will share my experiences about the places that we visited in the coming week!

Stay tuned folks!
Have some Fun!