Saturday, March 10, 2012

ASP.NET State Server - Why and How

If you have a web farm, then your web application is scalable, right?   WRONG.

If you web application uses session variables and if you do not configure your site to use out-of-process sessions, then your application is tied to a single server and you will have to do some magic on your Load Balancer to make each request (from unique IPs) "stick" to the original server.  This caused a problem in my company's environment because we have 2 reverse proxies that all traffic from the internet get routes through.  So our Load Balancer only sees traffic from 2 IP addresses and there for only uses 2 of our 3 servers in the farm to serve up applications.  So if we max-out our server capacity, even adding a 4th server will not resolve our issue as the load balancer with the "sticky" setting will still only direct traffic to 2 of the servers.

So, what can be done about that?  We can make it so that the application can be served by ANY of the servers in the app pool because their session data is accessible to each of the servers in the Farm.  This is done through the use of out-of-process sessions.  You can read a lot about session servers around the internet, but basically, out of the box, if you start coding using Session[] variables, it just magically works.  Most programmers starting out don't question HOW it works.  It is default behavior of ASP.NET and the Session[] variables you are creating in your app are being stored by the w3wp.exe (ASP.NET) worker process.  So, if you kill that process (like doing an iisreset), you will lose your session variables.  Also, if you load balancer sends your request to another machine (and therefore another w3wp.exe process), your Session[] variables will also be lost.

Some programmers resort to stop the use of Session[] and instead use a database and write their own access methods.  Other might choose to go down the VIEWSTATE path and keep their state in the screens.  But there is an easier way that allows you to keep you easy to use Session[] variables: the ASP.NET State Server.

On your IIS Server, when you install ASP.NET, a service called ASP.NET State Server is installed, but it is installed turned "off".  In order to use it, you must turn it on (that's about it), and you probably want to turn it on and set the start up mode to Automatic.

OK, so it's turned on, now what?  How do you use it?  Simple, place the following line into your web.config file:

How Civil Service Commission (Pre-Screen Application) was setup on QA for ASP.NET State Server.
For some basic Instructions, see:
http://dotnetguts.blogspot.com/2009/06/steps-for-session-inproc-mode-to.html
I turned on ASP.NET State Service on TempStaging by doing this:
1) Start >> Run >> Services.msc
2) "ASP.NET State Service" (installed automatically in "Manual Start" mode by ASP.NET)
3) Set "Start Up Type" to "Automatic"
Allow remote connections here (on TempStaging):
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\AllowRemoteConnection
In the application web.config, add this (in System.Web):
<--tcpip to 10.150.1.87 is the TempStaging server -->
<sessionState mode="StateServer" stateConnectionString="tcpip=10.150.1.87:42424" cookieless="false" timeout="120" />
Add a <machinekey> tag to your web.config as this is one of the unique identifiers the state server uses to identify sessions between different applications.
I installed the IIS6 Resource Kit (for the IIS Metabase editor) from:
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=17275
I tried using the Metabase Editor to make BOTH servers have the same "AppRoot" of:
/LM/W3SVC/1/ROOT/CivilServiceComm
per the knowledge base article found here:
http://support.microsoft.com/default.aspx?scid=kb;en-us;325056
and:
http://www.justskins.com/forums/asp-net-session-state-138611.html
But, in the end, I had to create the Moveinstance.vbs script from the knowledge base article.

Minify JavaScript through Google Closure Compiler and VS 2010

I have a project that is client-side heavy with jquery and the dhtmlx interface library and utilizing MVC & entity framework on the server side. I started building the JavaScript inside my views (.cshtml). But I knew at some point I was going to need to pull the JavaScript out into its own file (a trivial task), and Minify the code for at least a small degree of security.

Well, today was that day. After breaking the code into its own file, I set out to figure out how to automatically Minify the code. I had used online tools in the past to manually Minify my code, but in this day of automated build processes, I decided that a more automated approach was in order.

I googled obfuscated JavaScript and found that the most prevalent library seemed to the the YUICompressor from Yahoo, but the latest online tool seemded to be the Google Closure Compiler which has three modes: pretty, standard and advanced. Pretty simply structures your code to make it more readable with proper indentation and consistent block structures. Standard does the standard white space compression while advanced actually does code optimization and elimination of unreachable code. After choosing the google option, I also learned that perhaps there's a minifier included with visual studio?, but I ignored that option.

More on this subject later...

MVC3: Missing Unobtrusive Validation Attributes

The other day, I was testing some code that I had been writing for about a month.  At some point early on in the coding, I realized that all of my views had some common "hidden" elements that I was saving for each screen in a tabbed environment, so, being the clever programmer I am, I decided to move these common elements into my _Layout.cshtml file.  Of course, to do that, I also had to move my "@Html.BeginForm()" statement into the layout as well...

Ok...  so fast-forward to my testing...  suddenly, I realized that my client-side, jquery unobtrusive validation was gone.  I had not tested this for quite some time because for the past couple of weeks, I had been testing other parts of the code and always entered valid data.  So why did my client-side validation disappear?

Well, to make a long story short...  After several hours of debugging and reverting code back to earlier days (and weeks), with no luck in recovering my validation, I found myself staring at a "view source" of my code and noticed that one of my "common" variables HAD the unobtrusive data elements, but my view did NOT.

After some googling, I discovered that what was happening is that the MVC engine processes the inner view FIRST, then the outer _Layout.cshtml view (the one that has the "BeginForm()" statement in it.  Well, I found out that the MVC engine will NOT generate unobtrusive validation unless it first sees that it is in a BeginForm(0 construct, but since that construct is now in my _Layout, MVC does not think my View is in a form.

Now several programmers have various techniques to solve this, but the simplest solution that I found was to "fake" MVC into "thinking" there is a form in my view.  In the Views folder, there is a file called _ViewStart.cshtml that tells all of your sub-views to use a particular layout (you can override this in your specific view), but the file simply has this code:


@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

All you need to do to "fake" your view into thinking there is a form is add this line:


@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    this.ViewContext.FormContext = new FormContext();
}

Now MVC will think you have a form and will generate the unobtrusive client-side validation attributes.