Tuesday, September 27, 2011

Strongly Typed Session Using MVC3 And Spring.NET - Part - 2

In my previous post, we saw why its a good idea to have strongly typed HTTP Session. In this post we will do the real thing (well at least first part of the real thing).

Using Sping.NET we can control the objects lifecycle. By default the Objects configured in Spring.NET are Singleton for the entire application (singleton for scope="application"). Singleton for the entire application means, Spring.NET will create only one instance of the given object for the life-cycle of the application.  Service classes, DAO classes etc are a good fit for Singleton Pattern.

However, there are other Object Scopes that can be configured in Spring.NET.  These Scope's tell Spring.NET that, A given object is singleton but in a given scope.

One of the interesting scope is sessionSession scope is only available if we use a web-aware Spring IApplicationContext implementation.  For such objects, Spring.NET would create one instance per HTTP Session.  In this post we will see how we could take advante of the session scope, to create Strongly typed session in an MVC3 application.


Enough blabber.  Let see how exactly its done.

How do they do it!

As we had seen in one of the previous post to Integrate Spring.NET with MVC3 application, we had used the Spring.Context.Support.MvcContextHandler.  This class instantiates Spring.Context.Support.MvcApplicationContext, which in turn initializes the spring application context.

Support for session scope is porivded by spring.web.dll.  Unfortunately, as of Spring.NET 1.3.1, spring.web.mvc.dll does not depend on spring.web.dll, which effectively means, MvcApplicationContext is unaware of the session scope.

Hence, using just the MvcApplicationContext there is no way we can eable the session scope for a certain objects.  Its a bug you can find more details here.  But where there is will, there is a way!  There is obviously a way around this problem.

Here are the steps to enable full session scope support for any object in Spring.NET 1.3.1
  • Update the web.config to use a custom WebContextHandler
  • Register the spring WebSupportModule in web.config under the <httpModule> section for IIS6 and under the <modules> section for IIS7+
  • Implement the custom WebcontextHandler.  Override the property DefaultApplicationContextType.  This property informs Spring.NET about the class type of ApplicationContext that Spring.NET should instantiate.  This will be again a custom class that extends from Spring.Context.Support.MvcApplicationContext.
  • Implement the custom class that inherits from Spring.Context.Support.MvcApplicationContext.  This class will basically override two methods
    • CreateXmlObjectDefinitionReader to return the instance of WebObjectDefinitionReader
    • CreateObjectFactory to return the instance of WebObjectFactory
That's it!  We have now successfully enabled the session scope for Spring.NET 1.3.1.  Let look at the actual code.

Step - 1 - Update the web.config to use a custom WebContextHandler

Update the web.config configSection to look like

The class aspnetwebFormsWithMvc3App.Context.MvcWebContextHandler is our custom class where we will override the property DefaultApplicationContextType.

Step - 2 - Register the spring WebSupportModule in web.config under the <httpModule> section for IIS6 and under the <modules> section for IIS7+ 

Adding the spring module for IIS6 and IIS7

Step - 3 - Implement the custom WebcontextHandler

Lets look at the custom WebcontextHadler class aspnetwebFormsWithMvc3App.Context.MvcWebContextHandler

As you can see this class is pretty simple, it just overrides the property DefaultApplicationContextType to return the class type of custom WebApplicationContext.

Step - 4 - Implement the custom class that inherits from Spring.Context.Support.MvcApplicationContext

This is the class where the real work is done.
That's it! We have successfully enabled the session scope in MVC3 application using Spring.NET.

Question is: What is all this supposed to do with Strongly typed sessions?

In the next and the final post in this series, we will see how we can take advantage of session scoped objects to create the Strongly Typed Session in an MVC3 application using Spring.NET. 

Wednesday, September 21, 2011

Strongly typed Session with MVC3 and Spring.NET - Part - 1

In every Web project I have worked so far, always there is a need to store some or the other information in HTTP Session.

I am very finicky about putting things in the HTTP Session.  IMHO HTTP Session should be kept as light as possible.  There should be a very very strong and compelling reason to put a certain value in the HTTP Session.  Having said that, I do agree that there are times when we want to put certain information in the HTTP Session like user name, user id, etc.

With me so far?  Till now we understand that, we do not like to put things in HTTP Session, however, we understand that there is a definite need to put certain things in HTTP Session for the app to work correctly.

Question is, Is there an alternate to putting things in HTTP Session?

In this series of three posts we will try to answer this question.  We will try to use MVC3 and Spring.NET to eliminate the need of putting stuff in HTTP Session.

But wait a minute, let's first answer this question,

Why is putting things in HTTP Session is such a bad idea?  

Lets start by looking at the code that will put UserName into the HTTP Session.
Does it remind you of code that you have seen in one of your applicatoin? It certainly reminds me of code that is used all over the place in one of the projects that I had worked.

I totally hate to see code like this.  Why whats wrong with such code?

Session is used like a Hash Table:

In our example, key of the hash table would be UserName and value will be Git Shah.  Imagine while putting/retrieving values to/from the HTTP Session, if incorrect keys are used, results could be catastrophic.  Even a small typo like one shown in the example below would yield incorrect results
Ofcourse there are ways to get around this problem. Simplest of them is to use a Static Class that holds all the keys as constants.

However, you can still not gaurentee that every programmer on your team will always always use constant keys from the static class.  Believe me, because of human error or some other unexplainable reason, someone would use hardcoded inline key to put value in the Session and rest of the team will curse him/her for eternity! 

Session values are not strongly typed:

We have inserted a string value Git Shah in the HTTP Session against the key UserName but when we want to retrieve the value from the session we will have to typecast to its correct type.  In our example to retrieve the value of UserName key in HTTP Session code would look like
I have a name for code like that, I call it A Time Bomb!

Its just a matter of time before which you start getting a class cast exception.

Dude, whats in my Session? Where are these values used?

Can we say for sure what all values are stored in our session?  

Another important question to answer is, Can we say for sure, from what all places in the code are these values accessed?

These are a very important questions.  Answers to these questions are absolutely vital for the health of your application.

In one of the projects that I had worked, we were extremely confused for a very long period of time.  The question that was bothering us was, who was setting a specific value in the session and in what condition?

Consider an example

UserName key is populated in the LoginController.Login method. Lets look at another place where UserName is used.
AccoutController.UpdateUser updates the value of the UserName key in the HTTP Session to the new value passed as argument and AccountController.GetUserDetails method fetches the value of the UserName key from the HTTP Session and sets the ViewBag.UserName property.

As you can see in our simplistic example UserName key of the HTTP Session is used at three places.  In real life, it would be used in many more places than this.  The code that accesses the UserName key from the HTTP Session would be littered all over the place!

How will we find the exact places where UserName key is populated/fetched into/from the HTTP Session?

There is no easy way to find the exact places where UserName key of the HTTP Session is used.  We can extract a constant for the UserName and then search for its usages, but still this is not a full proof way, as I mentioned earlier, there are many fools out there who will not bother to use the constant and use an Hardcoded string key instead.

These are few of the problems that are a big concern to me.  Question to be answered is,
  • How can we avoid such code?  
  • How can we achieve an alternate option that will discourage people from writing such code?
Before we dig deeper into the solution, lets first focus on some of the design goals that this new solution should have.
  • Things that we put into and fetch from the session should be strongly typed objects.  There should not be any cast of any sort.  This will avoid Time Bomb like code.
  • Session should not be used as a Hash Table.  Whatever we put into the session should become a property of the session which can be accessed from anywhere in the code.  Moreover, because it becomes a property of the HTTP Session, we would get all sorts of intelli-sense on it.  There is no chance of any typo in this case.  For e.g. the existing code
Should no longer be required instead we should have code that looks like
  • At any point in time, it should be easy enough to find the exact places where a certain property of HTTP Session is used. In some ways this point is related to the previous point. If we are able to convert Keys of session into strongly typed Properties then we can just search for the usages of those properties and we know exactly where those properties were used!
Enough goals to start with.  Question is, Can these goals be implemented in real life? 

Well, the good news is, these goals are definitely implementable.  In fact its not too difficult to implement these goals when we use Spring.NET with MVC3. 


What is the bad news?  You will have to wait for my next posts to see how exactly we could implement these goals :)

Stay tuned folks in the next couple of posts we are going to have some fun with HTTP Session Management!

Tuesday, September 20, 2011

Calling a Stored Procedure with OUT parameters using NHibernate

Hibernate/NHibernate is one product that I appreciate a lot.  I absolutely love the flexibility that NHibernate offers.

Lots of ORM products out there work well when we are developing application from scratch, however they fail miserable when we have to work with existing legacy database.  Hibernate/NHibernate on other end, works very well when application are build from scratch as well as when we have to work with legacy database.  Hibernate/NHibernate provides lots of hooks because of which, using it with any legacy database is completely painfree.

In this post, we are going to see how we could use NHibernate to get around one such legacy issue.  One of the common technique employed in legacy databases to exchange information between the DB and Application layer is, having stored procedures with OUT parameters.  OUT parameters are special type of parameters in which the stored procedure returns values which can then be accessed by the Application layers.

We will not go into details whether OUT parameters are good or bad but, we will see how exactly we could use NHibernate to invoke stored procedures with OUT parameters.

Calling stored procedures without any OUT parameters using NHibernate is fairly straight forward, but calling stored procedures having OUT parameters using NHibernate is a bit tricky.  Without wasting any more time lets straight away dive into the solution.
How do they do it?


To call stored procedures with OUT parameters we have to fallback to the System.Data.SqlClient.SqlCommand (assuming that the database is MSSQL) to get the job done. 

Let's say that,
  • We have a stored procedure called encrypt that is supposed to encrypt any string
  • It takes INPUT parameter called stringToEncrypt
  • It returns the encrypted string as an OUTPUT parameter called encryptedValue 
We want to invoke this stored procedure using NHibernate.  The steps to do this would be as follows
  • Get an instance of Session using the NHibernateSessionFactory (or get it some how injected into the DAO class using Dependency Injection)
  • Start the transaction on the NHibernate session using BeginTransaction method
  • Create a new instance of System.Data.SqlClient.SqlCommand
  • Set the Connection property of the SqlCommand instance using the NHibernate Session's Connection property.
  • Set the SqlCommand instances CommandType property as CommandType.StoredProcedure
  • Set the SqlCommand instances CommandText property as the stored procedure name, in our case encrypt
  • Add the INPUT parameter to the SqlCommand instance.  In our case, adding the parameter with name stringToEncrypt and setting the value of the parameter to the string we want to encrypt
  • Add the OUTPUT parameter to the SqlCommand instance with Direction property set to ParameterDirection.Output.  In our case, add the parameter encryptedValue.  Since, this is an output parameter we will have to specify its SqlDbType as SqlDbType.NVarChar and size as 255.  But the most important thing here is, to set the Direction property of SqlParameter to ParameterDirection.Output.  This tells the SqlCommand that this parameter is an output parameter.  After executing the stored procedure we will be able to get the value out of this parameter. 
  • Enlist the SqlCommand instance with the NHibernate transaction.  This is another crucial step.  If this is not done SqlCommand will throw an error saying "ExecuteNonQuery requires the command to have a transaction when the connection assigned to the command is in a pending local transaction.  The Transaction property of the command has not been initialized" 
  • Execute the command using ExecuteNonQuery method on the command instance.
  • Get the output parameter value from the SqlCommand instance
  • Commit the NHibernate transaction and Close the NHibernate Session.
As you can see there are quite some steps involved while invoking a stored procedure with OUT parameters.  But looking at the code would definately make things easier.
And that is how its done!

Monday, September 5, 2011

Fixing the The virtual path '/test/currentcontext.dummy' maps to another application, which is not allowed

We have recently integrated Spring.NET in an MVC3 application.  In one of my previous post, I have already documented the detailed process of integrating Spring.NET with MVC3 application.  Spring.NET is really helpful when it comes to writing Modular, Testable code.  I totally recommend Spring.NET as Dependency Injection framework of choice!

We did a fresh deployment of our application on a new server.  On this computer, when we tried to access any of the pages of our application we got an error which looked like

Virtual Path Maps to Another Application, is not allowed
That was not very encouraging.  How can an application that was working correctly on all other servers stared giving exceptions for this particular server?

We tried to find out what were the differences between the other server and this new server.  We narrowed it down to one very interesting difference,  we used to deploy our project as a website in IIS on all other server.  While on the server that was giving us exceptions, we deployed our application as a virtual directory under the default website.  This very curious difference was giving us exceptions while initializing the spring context.

I Googled a little and found out that this is a known issue which has been reported here and here.

The workaround to this issue was simple enough, we just have to give a name the spring context in web.config

Would any random name work?  Do we have to follow some convention?

Our Spring.NET section in web.config file looked like
By now it should be clear that, we have to add a name attribute to node. But the question is, what value should it hold?

The answer is pretty simple, the Spring.NET context should be named after the virtual directory under which the application is deployed.  For example, if the virtual directory under which the application is deployed is called springmvc.  The updated web.config should look like

This did the trick! After making this change we were able to browse all pages in our application and Spring.NET integration with MVC3 application was working well!

Small issues like these have very simple solutions but, one might end up spending quite some time before finding a satisfactory solution.  I decided to document my finding for the benefit of the community!
Have some Fun!