Dave's Notebook

Bypass VPN for regular traffic

IMG_1380 For as many places as I’ve been where they use VPNs, I’ve yet to find one that is set up correctly.  I suppose there is a good reason for this, but I consider the problem to be mostly Microsoft’s fault. I mean, wouldn’t you assume that if it were possible to use your regular connection for all the network traffic EXCEPT for the traffic that needs to go through the VPN, that is what you would want?  But no.  Microsoft sets it up so that ALL of your traffic goes through the VPN connection.

Read More

Virtual Files using HttpContext.RewritePath()

One of the cool new tricks we are able to perform in ASP.NET that we were not able to use in ASP is the ability to have ASP.NET redirect file requests in the same way that mod_rewrite does under the Apache webserver.

For example, we could have the browser ask for an image file that doesn’t exist on the file system and have ASP.NET serve up the file from the database.

Read More

Why you can't cast an integer to a string.

I saw a question on Channel 9 that I’ve heard before. My guess is that there are enough people who have the same question that it’s worth addressing.

I know there’s probably a really good reason for this, but I can’t think of what it is, and it keeps bugging me. Why can’t you do int x = 10; string y = (string)x; in C#? I mean, you could simply use x.ToString(), but why doesn’t the explicit cast do the same?

Read More

Object Oriented Programming has Failed Us

I’ve been thinking about the state of the programmers coming into our industry recently.  It seems to me that many of the college students who graduate today understand the syntax, but few know how to apply true object oriented principles to the real world.

I recently had a discussion with a friend who confirmed my observations.  Simply put, most people do not think in object oriented terms.

Read More

Serializable attribute vs Serializable Interface

Judging from the comments I received yesterday, it looks like we need to review  serialization in .NET.

The Easy Way

There are two ways of making an object serializable.  The first, and easiest way is by applying the Serializable attribute to the class.  Once you’ve done this all of the member variables in the class will get stored into the stream unless you’ve attributed one of the variables with NonSerialized.

This method is useful for objects you want to be able to store temporarily.  For example, you might use this to transfer objects using Web Services or if you wanted to store the object in a session variable when your sessions are being stored in a session server.  You would never use this to store the object to a file that you want to be able to retrieve some time in the future after restarting your application.  That is, you would never use this method to implement the Registry solution I mentioned yesterday.

The Reliable Way

What you need instead is the Serializable Interface, or more correctly, you want to implement ISerializable on your class.  Using the ISerializable interface gives you a lot more control.  Used correctly, you can store an object to a file system, shut down your application, install an upgrade to the application with additional information (or less information) in the class, and still successfully load the object from the file system.  So, let’s illustrate with a simple class:

1
2
3
4
5
6
class Demo {
private int m_intVar;
public Demo()
{
}
}

The Basics

This is a pretty simple class.  It has one member variable that we will use to save some sort of state information and will need to get stored to the stream when we save the object instance.  To implement the interface, we need to change the class to look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Serializable]
class Demo : ISerializable {
private int m_intVar;
public Demo()
{
}

public Demo(SerializationInfo info, StreamingContext context)
{
m_intVar = info.GetInt32("m_intVar");
}

public void GetObjectData(SerializationInfo info,
StreamingContext context)
{
info.AddValue("m_intVar", m_intVar);
}
}

The thing to watch out for here is that you need a constructor that takes SerializationInfo and StreamingContext as parameters.  Since the interface can’t remember this, you’ll have to remember it.

You’ll notice that we’ve taken control of storing and retrieving the data by using the AddValue and GetInt32 calls inside of the new, required, constructor and the GetObjectData method.  GetObjectData is called when the data is being saved.  The constructor gets called when the data is being loaded.

Protecting For The Future

If we leave the code as it is above, we are no better off than if we had simply implemented the Serializable attribute.  What we need to add to this code is some way of versioning the object.  This is easy to do by adding a few more lines of code: When we initially create the object, all we need to do is add one line of code to our GetObjectData method

1
2
3
4
5
6
public void GetObjectData(SerializationInfo info,
StreamingContext context)
{
info.AddValue("VERSION", 1);
info.AddValue("m_intVar", m_intVar);
}

The Future

Some time later, we decide to add another variable to our class:

1
2
private int m_intVar;
private string m_stringVar;

And save it as part of GetObjectData.  Because we’ve added another variable, we need to increment the version number.  So, GetObjectData now looks like:

1
2
3
4
5
6
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    info.AddValue("VERSION", 2);
    info.AddValue("m_intVar", m_intVar);
    info.AddValue("m_stringVar", m_stringVar);
}

and our constructor now looks like:

1
2
3
4
5
6
7
8
public Demo(SerializationInfo info, StreamingContext context)
{
int VERSION = info.GetInt32("VERSION");
m_intVar = info.GetInt32("m_intVar");
if (VERSION > 1)
m_stringVar = info.GetString("m_stringVar");
else m_stringVar = "default string";
}

By incrementing the version number every time we make a change to the class and testing for the appropriate version number when we load the object, we can avoid having our application crash simply because the class has changed between the time we save the object and the time we loaded the object from the stream.