Wednesday, September 06, 2006

For a long time now I have been aware of this feature but still I think many users of Internet Explorer do not know about it. The feature that I'm talking about allows you to save a complete web page INCLUDING pictures to a single file so it can be used later without having to connect to the internet. This feature is accessible from the File->Save As... menu after you select the Web Archive (mht file) as a type of the saved file:

Note that there is also another option to save an entire page using the same dialog box and selecting Webpage, Complete option. This however creates one file for the page and a folder containing the rest of the required files such as images. This is not a very ellegant solution in my opinion.

As good as this feature is, there are occasionally problems with saving the page and the only information is that there was some kind of error (don't we love this kind of messages?). Other than that I think you will love it :-)

BTW: I haven't seen such a feature in the standard installation of the FireFox but I suppose that there is some plugin just for that.

Wednesday, September 06, 2006 9:41:13 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, August 29, 2006

Every now and then somebody just has to do it. They need to override the GetHashCode method either because overriding Equals method or for some other reason. Doing so, you should follow the guidelines provided to us by one and only Microsoft:

http://msdn2.microsoft.com/en-us/library/system.object.gethashcode.aspx

The main problem with guidelines regarding the GetHashCode method is that the change from time to time which causes some confusion.

The last change I have noticed is the fact that now GetHashCode can return different values for the same object if the state of the object that the GetHashCode relies on, has been modified. Previously GetHashCode allways had to return the same value for a given object (which caused it alomost impossible to override both the GetHashCode method and the Equals method and at the same time have a mutable object). The change to the rule makes it easier, but has some other implications...

The most important implication of having an object return a different hash code during its lifetime is the fact that no it is possible to put someting in the hashtable never to be seen again (at least not in a way we would expect it to). When this happens is when we put some value in the hashtable using some object as a key. Then we change the object so that it returns a different hash code and we have a situation where the value in the hashtable is inaccessible using the same key we have used to put it there.

As a quick example try the following code:

public class Class1
{
public override int GetHashCode()
{
return new Random().Next();
}

public static void Test()
{
Hashtable t = new Hashtable();
Class1 c1 = new Class1();
t.Add(c1, 1);
Class1 c2 = new Class1();
t.Add(c2, 2);
object o1 = t[c1];
object o2 = t[c2];
}
}

What would you expect o1 and o2 to be? Given no knowledge of the hashtable object I would expect to get what I have put earlier i.e.: 1 and 2, but I get nulls. That is because the Hashtable uses the GetHashCode method as a key to find values. Keep this in mind when overriding the nasty method.

kick it on DotNetKicks.com

Tuesday, August 29, 2006 2:04:18 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, August 23, 2006

In my two previous article on relational database schemas I have described problems that arise when dealing with sql database schema that needs to be changed. I have also provided a quick tip on using Enterprise Manager to get the schema of your database. Those are the problems of relational world...

As described in the mentioned articles there are problems when it comes to keeping your database schema up to date etc. There are also problems when you need to keep the application code in sync with a database. Either you do a database-driven design and add fields in a database and then adjust the model to reflect this change, or you do a more model-driven design i.e.: the other way around - change the model and then adjust the database you always have the problem of synchronization. Tools are available that generate either a model or a database from eiher the database or the model, but is it perfect?

Far from it. One thing that I really appreciate when using Db4o is that I have no such problems. Simply because there is no database schema or in other words: the database schema reflects what I have in my model.

Now I'm not suggesting that object databases are the solution to all your problems. There are problems with data migration also however I haven't encountered one yet.

Wednesday, August 23, 2006 1:40:57 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

As promised in my article on upgrading database schemas, I will show you the trick that I have learned when I was preparing SQL database upgrade scripts for my databases (that is before I thought on using some automation such as SQL Delta).

The fastes way I have found to get the database schema from a Microsoft SQL Server 2000 is to use the Enterprise Manager. Just navigate to a database you want, select the Tables node and select the tables you want to get schema for (you can select multiple tables using either shift or control key). As an example I have selected two tables of MyGallery database:

Having selected the desired tables use the context menu and select Copy or use the ctrl+c shortcut. Now open some kind of text editor such as Notepad. Paste the content of a clipboard and what you get is something like:

Now that is very cool isn't it? I have used this technique fo comparing two databases some time ago. Just get the schemas from two databases, save them to files on your disk and use some text diff tool.

Far from perfect but if you have no tool this is what you got. One more thing to mention is that you can use this copy and past mechanism also with stored procedures.

kick it on DotNetKicks.com

Wednesday, August 23, 2006 1:28:01 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Every now and then there comes a time when you release a new version of you application. Some of the new versions do not require changes to the database schema, but there are times when such a change needs to be done.

So imagine that we have an application that several hundred of our customers run. The best possible situation is that all of them have the same version of a database schema. Then we do not have to test all the possible upgrade scenarios. Mostly however there will be multiple versions of databases that are out there and you have to handle all of them.

But what is really the problem you ask? We have developers that designed the database at some point in time, created an application that was sold with that particular schema version. Then, upgrades were made, between that version and the version that we are about to release now and developers have been told to create SQL upgrade scripts so that the we can ship them with a new version. All fine if developers were doing those upgrade scripts while changing the database. Worse if you have to make a diff of the initial database schema and the desired one. Either way it was, is and always will be prone to human error. People are error prone. We, developers make mistakes, especially when doing some mindless (most of the time) activities such as comparing databases.

So, how sure you are that the database upgrade scripts that you are about to ship are the right ones? Hard question. One thing you could do is to take an initial database, run the scripts and compare the schemas. I will post a short tip on how I do it with Microsoft SQL Server 2000 Enterprise Manager. If there are errors, correct them, run the scripts again, repeat until there are no differences (or you see none).

Another problem is that the schema is not the only thing that needs to be shipped. Imagine that there is some fixed data in your database that is constant. Imagine that this data need to be altered. Same solution exists as mentioned above. Do it by hand either at the end or incrementally.

Is this solution perfect? Is it cheap? Is it time and cost effective? When you think about it you will find out that there should be some automation available. And rightfully so. There are tools that let you compare the databases, point out the differences and even create an SQL upgrade script for you. Keeping in mind what was said earlier it should be obvious that such a tool is a must have tool in every software development company that does sometime upgrade its databases.

As mentioned, there are tools that help you automate this process. I have recently found the SQL Delta application that lets you do eliminate this time consuming and error prone process of manualy generating upgrade scripts. Now if I had such a tool back when I was wasting my time making the scripts instead of solving the real business problems...

kick it on DotNetKicks.com

Wednesday, August 23, 2006 1:05:41 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, August 18, 2006

Today I have added a little "Add to del.icio.us" link at the bottom of each article. Feel free to use it :-).

Now the technical stuff. First of, for the blog engine I'm using ThinkJot. It is an ASP.NET 2.0 port of a popular dasBlog application. As any dasBlog user should know, the engine supports macros with which you can add some dynamic content to your posts. To use them you have to edit your template and use something like <%itemTitle%>. There are plenty of macros documented on the official dasBlog site and even more macros are supported that are not documented - or at least I haven't found the documentation.

So the procedure I went through while adding a del.icio.us link was a bit painful. First of when you google for an answer what you find is mostly far from perfect. Most sites just suggest adding a simple linkt to del.icio.us and provide some parameters in the url. What I have found on the del.icio.us site was far better.

The solution from del.icio.us by default uses javascript and a popup window for adding links and if javascript is not enabled it works just as a simple link.

The hard part was to integrate the solution with the dasBlog macros engine. I have found a dasBlogExtraMacros.aspx">ready made solution. I have needed something more customizable so I have not used it however. I have editted my itemTemplate.blogtemplate file by adding something like this below the item text:

<a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&noui&jump=close&url='+encodeURIComponent('<%permalinkUrl%>')+'&title='+encodeURIComponent('<%itemTitleText%>'), 'delicious','toolbar=no,width=700,height=400'); return false;"> Save This Page</a>

It is basicaly the script offered by del.icio.us but I have replaced the location.href with a standard permalinkUrl macro which I think is not documented. Secondly I have replaced the document.title part with itemTitleText - my own macro that returns current item's title as text. There is of course an itemTitle macro but it is an html anchor so it cannot be used (this can be changed in the config file, but since I want my article titles to be links I could not do it).

Creating the itemTitleText macro was very easy. All I had to do is add a property to an ItemMacros class as follows:

public virtual Control ItemTitleText
{
get
{
Control control;
string title = entry.Title;
if (requestPage.SiteConfig.ApplyContentFiltersToWeb)
{
control = new LiteralControl(Utils.FilterContent(entry.EntryId, title));
}
else
{
control = new LiteralControl(entry.Title);
}
return control;
}
}

That's it. I now have a del.icio.us link :-)

kick it on DotNetKicks.com

Friday, August 18, 2006 12:15:41 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, August 10, 2006

There is a feature in Visual Studio 2005 called Code Snippets. Basically what this feature allows you to do is type in a code editor, some special string such as "prop":

And then by pressing the TAB key once (or twice if using the provided intellisense), Visual Studio generates some code for you as on the picture below:

Notice that there are reqions highlited witha green color. You can tab through those regions with a TAB key. On the above example, If you eddit the type of the field, the type of the property is automaticaly updated for you. The same holds true for the field name which is used inside the property.

Visual Studio 2005 comes boundled with a couple of useful code snippets of which I use the "prop" the most. However, If you do mostly ASP.NET applications you know that the standart property with underlying field is not so widely used here. What we need is a property which uses ViewState as a storage medium. Fortunatelly it is very easy to create your own snippets. Just go to the folder where VS is installed - for me it was: "c:\Program Files\Microsoft Visual Studio 8\VC#\Snippets\1033\Visual C#". There you will find all the available snippets. When you look any one of them what you will find is a simple xml defining the snippet behavior. From there it should be no problem to create your own snippets.

Being ASP.NET developer myself I have created few snippets that help me doing my work faster and those are: propv, propvd, props and test. First two generate a property that uses the ViewState, the third one generates a static property and the third one a method that has a Test attribute of an NUnit testing framework. You can download the snippets here: Snippets.zip (2,23 KB). Just put them together with the rest of the snippets.

As a side note I must say that I'm mostly a C# developer, but I have written my share of the code in VB.NET so I know what I'm missing using C#. One of the things that I miss is the snippet support. VB.NET comes with WAY more standard snippets and those snippets can do a lot more such as add a using statement or a reference to an assembly. There are even application that support creating snippets for VB.NET. Given the limitations of C# snippets I don't think we need such a tool at the moment :-(. Additionaly I recommend browsing the internet for more information as this article is just an overview of what else Visual Stidio can do for you if you just ask :-).


Do you own a business that requires the latest in wireless barcode scanner technology? Find this as well as a wide selection of barcode printers or a the best brands of credit card reader at the barcode experts.

kick it on DotNetKicks.com

Thursday, August 10, 2006 10:51:58 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Tuesday, August 08, 2006

Since I have first seen Db4o database it has became my database of choice for every personal project that I do. You can read more about this database on its home page and I strongly recommend you to do so, even if you are not planning to leave the relational world. Reading about object databases will broaden your horizons and maybe it will change the way you implement your applications as it changed mine.

Tuesday, August 08, 2006 8:09:01 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

In the first article about optimizing rendered page size I have pointed out that you should consider using short names for content placeholders on your master pages because each control's id inside those placeholders is prefixed with the id of the placeholder. But when you look inside the page there is of course another field where you can make some improvements - the ViewState.

There are lot of articles about what you can do to make the ViewState smaller. Mainly - disable it everywhere where it isn't needed. This is a first step you can take. Amongst other things you can also use the SavePageStateToPersistenceMedium and LoadPageStateFromPersistenceMedium methods of the Page class. The purpose of those methods according to MSDN is to save and load any view state information from and to a page object. And that is true. But how to use those methods?

Browsing the results returned by google you can find plenty of solutions out there each unique in its way. Why they are different? The problem with those methods is not saving the state. To save the state you can use anything from the Session object, flat files or even database. The real problem is making sure that when a form is submited to a server, its ViewState is properly loaded - the concrete ViewState that was saved for that concrete page. A solution to just use Session["ViewState"] as a storage medium won't do, because then we can only have one ViewState for each user - no multiple windows/frames allowed.

My solution would be to include a hidden field on each page, name it somehow and use its value as a key for identifying which ViewState to load. Such a hidden field may be added dynamicaly in a base page so no additional work is required when adding new pages to a project. This field of course shoud hold some unique value (such as guid) in order to distinguish one page request from the other.

kick it on DotNetKicks.com

Tuesday, August 08, 2006 7:41:13 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 

I'm in process of creating one web site on which I needed a checkbox but I needed it to de displayed in form of an image. So I went to google and performed a search for a ready to use control. What I have found was not satisfying at all so I have created my own and the result is available within my controls pack as along with some other controls here.

Tuesday, August 08, 2006 2:05:25 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |