A while back, I was asked a question by one of the junior developers here at Lake Quincy Media. I had him working on a little feature on an ASP.NET site which could be easily handled using Session. "Where is session stored, on the server or the client?" he asked. As a quick response I said that it's stored on the server. He followed that by saying, "So it doesn't use a cookie?"
And that was all it took to set me on one of my usual lengthy explanations of how a piece of functionality actually works.
How is ASP.NET Session stored?
In ASP.NET, session data is stored on the server. It is stored in a per-user basis and maintained only for a limited period of time. Anyone who has used sessions knows that it is accessed during server-side code execution and is accessed using strings as keys. So we know that Session data is stored as key-value pairs. The following is basically how we access the session information. In this code I store a string in Session and pull it back out from session.
string name = "Brendan Enrick";
Session["fullName"] = name;
string nameFromSession = Session["fullName"] as string;
Pretty simple really. It is a nice way to store data for a user during this visit to the site.
How are users associated with their session?
In the default scenario for ASP.NET Session, cookies are used. No, the data is not stored in the cookie. When a Session is started on the site, the user is given a cookie (yummy cookie) which contains a unique identifier for accessing the session. While the user navigates around the site, the browser sends the cookie information to the server. This is what keeps the user associated with his session. Each time the server receives the cookie from the user so when your code requests data from session, it is pulling the data from the session associated with that user.
Can cookies be avoided?
Yes, it is possible to avoid using cookies. Session is able to run without cookies by setting a boolean property in the web.config file to true. The property is called cookieless and it is on sessionState. When session is not using cookies it instead places the SessionId in the url the user requests. Internal links on the site contain the unique session id so that the processing which occurs on the server is able to access the correct session values. I prefer not using this method because it just makes URLs all over the site look terrible.
How long are values saved in session?
By default the timeout for session in ASP.NET is 20 minutes. This means that the session will expire 20 minutes after the user last accessed the site, so as long as the user continues using the site it will not expire. If the user waits 25 minutes before clicking a link, the session will have expired. It is easy to adjust the length of time before sessions expire. In the web configuration file you can simply adjust the value for timeout on the sessionState element.
<sessionState cookieless="false" timeout="45" />
And this is why asking me questions can be a bit crazy. I'll first go on a lecture about the topic and then eventually I'll publish a blog post so I don't have to lecture again. Now if someone asks me that question I'll send him here.
Continuing on my previous post about separation of code responsibilities where I was mostly just discussing one aspect of a book I appreciate, I now want to comment on the concept of separation of concerns. While thinking about this idea I realized that I've been a follower of this idea longer than I previously thought. I admit it, I don't separate my code as well as I often could. I am sure that everyone reading this has heard that we should try to make things modular and that we should encapsulate pieces of our code. It is all part of what I consider to be classical education taught to programmers everywhere.
Separation helps for many reasons. It allows us to think about only the currently important section of code. We need not always be concerned with how everything else works. It is much easier to solve problems by implementing a solution that doesn't require at every step being concerned with the details. If I want to tell someone how to load boxes into a truck. I want to say something like this.
- Pick up a box
- Place the box in the bed of the truck
- Repeat previous steps until no boxes remain outside the truck
I don't want to have to do something like this.
- Pick up a box
- Move next to a box
- Bend knees so you're at about the same level as the box
- Put hands on the box
- Grip the box tightly
- Lift up using your knees
- Place the box in the bed of the truck
- Move while still gripping the box
- Walk over to the back of the truck
- Move box away from body and toward the truck
- Let bottom of box touch the truck bed
- Release grip on the box
- Move hands away from the box
- Repeat previous steps until no boxes remain outside the truck
I prefer to be able to assume that the person I am talking to knows the simple things. If I have to get into this kind of detail anytime I tell someone how to do something I am going to forget details along the way. I'm going to say something incorrectly. I also may mess up the overall algorithm because I am too concerned with the details of the steps. With different pieces being separated it makes it much easier to solve problems. There are plenty of other reasons to separate what we create.
Another reason that it is nice to have our work separate out nicely is that we are able to replace and adjust sections of our work without having to rip it all apart. If I have been having sections of code performing plenty of different tasks then I make it a lot harder to change it. When I go to make a change I am dealing with a lot more than I need to be, because a lot more stuff is there. The benefits of this are plenty and I am sure people can suggest plenty more. (I am also sure there are plenty of reasons to not have modular code.)
As I am sure is the case for many developers reading this, I spent a lot of time working with Linux machines. One thing I of course noticed with the classic applications found in the open source world is the tendency to have individual programs perform one task. The output of one program is often passed as input into the next program.
One line I heard often is, "Why does program xyz need to sort its output? Just send it through program abc, because it sorts already." At first I think the idea of having a program for sorting is kind of silly. Isn't it easy to sort? Couldn't all of these programs just sort? Well even sorting text can be fairly complicated. Which algorithm should you use? Should sorting be on the first character or the second? Maybe we want to sort based on the second column of data. I don't want to go into the code for a large number of programs just to update how it sorts.
Along with separation of concerns comes the also very important need to break dependencies. When we perform this separation we are breaking things into separate objects, libraries, and who knows what else. Some dependencies aren't a big deal. Most of my applications are fairly dependent on the .NET Framework, but I am not concerned with this. If I am stopping using the .NET Framework, I am probably switching languages or something and rewriting anyway.
While thinking about how to break up responsibilities among sections of code I've really been noticing how great an idea those separate programs have always been in the Linux world. I've noticed a trend away from it, but the core applications still tend to follow that old principle. Keep things small and performing only one task. Need something else? Let another program handle that task. As any code attempts to do more, it just becomes more difficult to work with.
The idealistic purpose of computers is to make our lives easier. Try not to let them do the opposite.
One book I would highly recommend reading is Working Effectively with Legacy Code. I should write a review of this book at some point, but for now I just want to mention one great thing about it. Reading the book is very valuable, but it is an excellent reference book. Many of the chapters of the book are devoted to certain scenarios which might arise when dealing with legacy code. It then goes on to explain how to handle these situations.
At the moment I am attempting to change some code which needs to make a bunch of API calls. Right now the code is not neatly written and methods are directly interacting with the API, performing in-memory work, and calling methods to save data. Since I am relatively new to this stuff, I figured I'd read the chapter titled, "My Application Is All API Calls".
In the chapter, the author uses a simple example about a mailing list server. The application is a big jumbled up mess. As the text preempting the code states, "We're not even sure it works". This type of situation is exactly what I am trying to avoid, and a great way to know something works is to have tests written for it which demonstrate the code's ability to function correctly. The tests are also a great way to show what a piece of code does.
When the author is discussing how to design the application in a better way, he mentions his desire to separate the code's responsibilities. Now I know that separating code responsibilities is important, but his example really shows it well I think.
1. We need something that can receive each incoming message and feed it into our system.
2. We need something that can just send out a mail message.
3. We need something that can make new messages for each incoming message, based on our roster of list recipients.
4. We need something that sleeps most of the time but wakes up periodically to see if there is more mail.
The nice thing is it then becomes so much easier to work with the API calls because they've so nicely been separated. One mistake I've made in the past is not separating out the code which needs to periodically perform some other action. I have attempted in the past to link that together with the code performing the local work. BIG MISTAKE!
Right now what I am planning on writing is going to have these separate responsibilities:
- Something to fetch data from an external source.
- Something to manipulate the retrieved data into its desired format.
- Something to store the data internally.
- Something to periodically check for new data.
Notice the incredible similarity there. It is very nice for my application, because only one piece needs to know about the API, and only one piece needs to know how the data is stored. Instead of before where some of that was a bit muddled together. This separation keeps the code cleaner and much easier to code. Testing will also be a lot easier because of this separation.
One of the most difficult parts about testing code well, is that lots of code is not separated well enough to be tested. Being too tightly connected to an API makes code nearly impossible to test, so it is hard to tell if a piece of code is working or what it does.
Lately I've been taking a look at dependency injection, and I've spent a little bit of time examining Ninject. I've read most of the Ninject Documentation, and so far I'm very interested in it. I love that it doesn't depend on configuration files. The "modules" it uses look very interesting. Whenever possible I prefer to use strongly typed everything. I love the compiler and everything it can do for me. I also love intellisense, and not depending on config files helps me to use both of those.
I've heard a little bit about some other dependency injection frameworks including Windsor and StructureMap. Not really sure what people are using. I'm pretty well sold on Ninject for now, so if anyone has any opinions or information I need to consider please let me know. I would be glad to hear what other people are using and what their opinions are.
Dependency injection makes a lot of sense, but with a few different choices out there, it is hard to say which route someone should take. I also like the fact that ninject seems to be a lot lighter weight than some other frameworks. In general I prefer add-ins which have very small footprints. If there is one thing I can't stand it is code that dominates everything else.