When Node.JS started getting popular, one of the major benefits people were proclaiming about it is that the web servers running under Node.JS were all processing the request asynchronously. This is how a single threaded environment was able to handle a significant load without falling over. Cool! So, you might wonder how does ASP.NET process request? It processes code synchronously. So, one might assume that if there were a way of running code asynchronously, we might be able to improve the performance of our applications. But can we? And if we can, is it worth it?
As I’ve written before, I’m using Angular a lot recently to write the client side of my web applications. As I’ve gotten to the end of my current project, I found myself needing to implement cache busting and while I am at it compression. But because I’m using a regular HTML page to serve up the shell for my single page application, using the regular ASP.NET on the fly compression wasn’t going to work for this application.
But there are a lot of tools in the Node.js space that will work. Would it be possible to wire node.js and Gulp with ASP.NET in my existing web project?
It turns out you can. Although, at this point, it isn’t as straightforward as most other things in Visual Studio.
I’ve been looking at Angular.js recently. I’ve already got enough of a project done in MongoDB (with Mongoose), Express, Angular and Node.js (MEAN) to be comfortable with how Angular works. But I wanted to give it a try using ASP.NET as the back end. I’m always learning. Always improving.
To start out, I just setup an index.html page to hold my basic form as I got the basic look and feel going. But as I progressed, I wanted to make sure I progressed, I wanted to add in the capability of using Angular’s html5mode for the client side routing.
Out of the box, Angular, and most other frameworks that implement client side routing, using the hash symbol to specify the route. For example
This allows the routing to work on older browsers.
ASP.NET, Angular.js & html5mode
This happened a couple of years ago, but it is still relevant because I know of at least one place where it is still happening even though Microsoft has fixed the issue that initially caused this hack to be put in place in the first place.
Problem In Production – Oh NO!
Here’s the problem we were seeing. We had several large PDF files that the client wanted to put up on the site so that their customers could download them. The problem that we were seeing is that even though the site worked fine under development and QA, the site seemed to consume a lot of memory under load.
Another symptoms we saw was that the file download took a lot of time to start, or timed out completely. But the main issue was the memory because when the memory was consumed, the site would restart, and because it was a worker process crash that caused it, the restart took the site down. This is not something you want to see happen when you are working with a client with world wide exposure. A client who, if I told you the name, I’m sure you would recognize.
In fact, it was the site not responding, or crashing, that first alerted us to the problem. So, as soon as we knew the site wasn’t responding, I’d log onto the server and fire up task manager to see what was going on.
Server Management Tip
One of the things I did early on managing the servers, is that I set up an entirely separate app pool for each of the web sites we are hosting. This way, we can monitor the memory and CPU activity of each one independently. For those of you who are interested, the way to make the pool name show up in task manager is to run the pool in ApplicationPoolIdentity, a setting you can get to through “Advanced Settings…” If you are only hosting one site, you shouldn’t need to do this, but in my case, with multiple sites, this told me a lot about what was going on with the sites and ultimately helped me track down what the problem was.
By the way, you should always run each of your sites under a separate application pool so that when one site is having trouble, every site on your server doesn’t have trouble. Imagine having an issue and not even knowing for sure which site was causing the trouble. It’s bad enough not knowing what page is causing the problem.
It Is a Memory Issue. Now What?
OK. So, I could see the memory increasing as soon as the site came back up. So, now to try to track down what was causing memory issues.
I tried various things along the way, none of them shed any light at all on the problem. I even got dotMemory from JetBrains to see if I could find anything. A memory leak maybe? No, none of my code had even a small leak.
The Fix Discovered
And then I finally stumbled on the issue. I can’t remember what it was that we installed that needed this, but what it did was change our web.config file so that it had a section in it that looks like this:
<configuration> ... lots of other configuration stuff ... <system.webServer> <modules runAllManagedModulesForAllRequests="true">
Make sure that runAllManagedModulesForAllRequest is either set to false, or doesn’t exist in your web.config file. If you need it to be turned on for some valid reason that I am not thinking of, at least put your static files on another site where this can be turned off.
Moral Of The Story
Now, the question that we should be asking now that we’ve figured it all out is, why wasn’t this caught earlier? When a site goes up, isn’t all of the functionality, including all of the links to all of the images, files to download, and other pages on the site and off the site supposed to be tested?
Yes, of course they are, but if you haven’t at least written down where all of this is, if you don’t have a systematic way of testing EVERYTHING, you WILL end up with these kind of errors once you put the site live. This is to say nothing of load testing along the way. This can all be prevented.
I just finished listening to a DotNetRocks podcast today with Paul Sheriff which largely talked about creating mobile web sites using ASP.NET WebForms.
During the show they discuss when you might use WebForms vs MVC and pointed out that WebForms still have their place, particularly in the corporate world, since they are just as testable as MVC and yet much easier to get something up and running quickly. This is in contrast to a public facing site that might need to be as light weight as possible and therefore need the extra control that MVC can give you.
And then there is the issue of legacy code. As they mentioned in the podcast, just because Microsoft has introduced a new technology, doesn’t mean we all have to go re-implement our websites in that technology the next day. It doesn’t even mean we have to ever implement that technology. It is just another option in our toolbox. It is our job as developers and architects to know when the right time to use what technology is based on the requirements of the application and the skill set of our development team.
The War Is Over
The point I want to make today is this. The war is over already. I am surprised that this is still a conversation that the community is having. Both sides have “lost” to a sneak attack by SPAs. If this is still a conversation you think is worth having, I would suggest that you may be behind the learning curve. The .NET world has moved on.
That is, client side models and frameworks have taken over. What you use to produce the HTML that all lives in, is of very minor concern at best.
- Find Your School
- Participating Products
- The “UPC Lookup” tab on the Participating Products page above
- Much of the Signup logic on the LabelsForEducation web site
You would be surprised at how very little code is in the codebehind files of my ASCX files that each of my modules live in.
In my current project, I’m using EXTjs and ExtDirect, which is based on WebAPI, to create SPAs. Nothing that I am currently doing requires that I do the work in either WebForms or MVC.
The beauty of an SPA is that it never officially post back so it doesn’t matter what you are using to hold the main application.
Drawbacks to SPAs
And what if your page has no interactive components? Or just a part of the page has some interactive components? Maybe the bulk of the content comes from a database. In that case, you can use either and neither would necessarily be “bad.”
What About Database Driven Static Sites?