Friday, July 20, 2007

For a couple of months now I've been running Windows Vista and Visual Studio 2005 without major problems (other than the commonly known ones). Since the first day of this setup I have been working on solutions that inlcude from one to many ASP.NET web applications. All of them are configured to use IIS rather than the built in web server. For all that time, everything was working fine until recently...

One of those days, while opening one of the solutions in Visual Studio, I was presented with a message telling me that my site is configured to use ASP.NET 1.1:

---------------------------
Microsoft Visual Studio
---------------------------
The site 'http://localhost/WebSite' is currently configured for use with ASP.NET 1.1.4322.573. Microsoft Visual Studio has been designed for use with ASP.NET 2.0; if not configured some features may make incorrect assumptions, and pages designed with the tool may not render correctly.

Would you like the site to be configured for use with ASP.NET 2.0?
---------------------------
Yes   No   Cancel   Help  
---------------------------

Needles to say that there were no changes made to IIS configuration of Application Pools or the pool the site is running on, but just to be sure, I've checked IIS Manager. The pool for the site was ASP.NET V2.0. I have agreed and allowed Visual Studio to make the "necessary" change. Needles to say, that nothing was changed in scope of application pools by Visual Studio. Fortunately, my solution kept working after that... for few days.

After few days I've got the very same message. Again, nothing was changed in IIS. This time I decided to leave my supposedly ASP.NET 1.1 in place. Of course everything worked after that also. Including debugging! But then I have the same message every time I open any of the solutions :-(.

I have found that other people also had this problem, and "aspnet_regiis -i" helped them, but it doesn't work for me :-(

Today I noticed that it gets worse. Now I get the message every time I open any of my solutions that include web sites :-(

Friday, July 20, 2007 2:05:07 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [3]  | 
 Sunday, July 15, 2007

ASP.NET despite its many nice features, has also a lot of nasty ones. Some of them are critical - like a design flaw in the way controls are rendered - by the controls themselves (only in version ASP.NET 2.0 Microsoft introduced the concept of Adapters, but this thing is beyond repair. There is just to much logic already in Render methods of all the existing controls to make using adapters easy). Others are just plain annoying, but we mostly we can live with them and even find workarounds.

Today I simply had enough of the style="border-width:0px;" attribute that ASP.NET adds to every img tag it renders from the Image control. There is strightforward way (that I know of) to remove this thing! Try as you might, there will always be a border-width style attribute on you images with either 0px, or whatever value you assign in you ASPX file. But there is a workaround.

To make the border style gone, we have to create our own Image control (inheriting controls is usually a good thing). In this control we have to resort to a trick of overriding the BorderWidth property by returning anything other than Unit.Empty:

public override Unit BorderWidth
{
    get { return Unit.Pixel(0); }
    set { ; }
}

This will cause the border style not to be rendered at all. Additional side effect which is obvious when looking at the above code is that now it is impossible to set BorderWidth property in any way. The value will alwyas be Unit.Pixel(0). This is also a good thing since we really shouldn't set any of the style properties inline but rather use a css style sheets for this purpose.

Sunday, July 15, 2007 2:39:59 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [6]  | 
 Saturday, July 14, 2007

From time to time, there is a need to get something from a file system in our ASP.NET applications. In those cases, we use the Server.MapPath() call on our pages classes. But what about class libraries?

Usually in class libraries in order to get the physical path of a file on disk we can use something like HttpContext.Current.Server.MapPath() and it works as long as there is a context i.e.: HttpContext.Current is not null. Sometimes however it may happen that there is a task running on the server which does some work without any request being processed. What then?

Enter the HostingEnvironment.MapPath() method where HostingEnvironment is a class defined in System.Web.Hosting namespace. It works the same way, as Server.MapPath() but it is a static method requiring no context to be present.

Saturday, July 14, 2007 5:46:21 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Thursday, July 12, 2007

ASP.NET Pages offer us a declarative way to set some of the properties such as Theme, MasterPageFile or Title in the Page directive. A nice feature indeed. The problem is that the same ASP.NET or maybe the Web Forms framework and Visual Studio stand in our way when we try to set our custom properties this way. It is possible but not developer friendly in a least.

To do it, we have to use the CodeFileBaseClass property and set it to the same base class that our page inherits from. More on this on K. Scott Allen's blog. Although it is technically possible to set this attribute to some class upper in the hierarchy I have encountered random weird behavior of Visual Studio after doing so. To be safe it is better to use the same base class both in the inheritance and in the CodeFileBaseClass attribute.

What about generic types? The tool (Visual Studio) support for generic types has never been great (not to say there is virtually no support). The fact that Visual Studio makes it hard to use CodeFileBaseClass difficult does not make it easier when it comes to generic base pages, but it can be done!

Suppose we have a type in the App_Code directory:

public class MyType
{
}
And also, defined in the same directory, we have a base page class:
public abstract class BasePage<T> : Page
{
}

And finally there is a Default.aspx page in the project that inherits from the our BasePage class:

public partial class _Default : BasePage<MyType>
{
}

Obviously we cannot just put a type name as BasePage:

CodeFileBaseClass="BasePage"

It won't work, because there is no such type. The message is: "Could not load type 'BasePage'". Our type is generic so we have to use it's full name:

CodeFileBaseClass="BasePage<MyType>"

But this also won't work. It will fail with the same message. That's becuse it is a C# specific representation of a generic type name. What CLR sees is something different. In order to make it work with a generic class we have to lower ourselves to the CLR level and use it's notation. This would mean using something like:

CodeFileBaseClass="BasePage`1[[MyTypebecause]]"

This thing actually works! If your types reside in some kind of namespace, has many generic parameters or worse yet, is part of a strongly named assembly, the whole CodeFileBaseClass starts to look scary and I don't think it is worth it. There is a trick however that may civilize the thing you enter in CodeFileBaseClass that allows to use any kind of base page class without making it complex. Just create an intermediate class like this:

public class StandardBasePage : BasePage<MyType>
{
}

and inherit your page from it. Than you can use this new type's name in CodeFileBaseClass without having to deal with generic parameter issues.

kick it on DotNetKicks.com

Thursday, July 12, 2007 4:56:35 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, July 11, 2007

Since my first days of using Windows Vista I have noticed that the "Documents and Settings" folder is somewhat different than it used to be in Windows XP. The main difference is that it no longer exists. Not as a directory at least. The new place for your-everything is now the Users folder - a good choice if you ask me - I've never liked the long name with spaces inside. But how are all the applications that rely on "Documents and Settings" supposed to work? And what is the "Document and Settings" "folder" that we see on our disks?

The answer is simple: symbolic link. A thing that every Linux user knows and loves. A thing that is almost never used on Windows platform.

I have noticed that there are two types of "symbolic links" in use in Windows Vista. If you go to the Users directory using command line and invoke a "dir /a" command, you will get an output similar to the following one:

2007-05-16  17:06    <DIR>          .
2007-05-16  17:06    <DIR>          ..
2006-11-02  15:02    <SYMLINKD>     All Users [C:\ProgramData]
2006-11-02  15:02    <DIR>          Default
2006-11-02  15:02    <JUNCTION>     Default User [C:\Users\Default]
2006-11-02  14:50               174 desktop.ini
2007-07-11  21:13    <DIR>          mikeon
2006-11-02  14:50    <DIR>          Public

Notice that the <SYMLINKD> and <JUNCTION>. From what I've been able to learn, the <SYMLINKD> is the new feature in Windows Vista, that replaces the old <JUNCTION>.

So how to create a symbolic link? I've found no way to do it using GUI. The only way I have found is the command line tool "mklink".

Beware however, before using this feature. Some people report that it may not be 100% transparent for your application code. So if you try to get something from "Document and Settings" it may not be there.

Wednesday, July 11, 2007 9:12:10 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Monday, July 09, 2007

There is a very useful feature in Visual Studio since I remember. It is accessible through Debug->Exceptions... menu item. It allows you to specify when you want the debugger to break. By default, it is when an exception is unhandled, but to make sure, everything works as expected, I often turn the when thrown option on. This allows me to detect all exceptions that are thrown in my code, even those that I handle but shouldn't.

Normally the Exceptions window looks like this:

But for some unknown reason, mine looked like this:

Notice that there is no User-Unhandled checkbox column. For some reason I just needed to have this column so I went searchin over the internet, and I have found that the reason for not having the checkbox column for User-Unhandled exceptions is the setting I have made in some other part of Visual Studio: Tools->Options...->Debugging->General->Enable Just My Code (Managed Only).

After checking the above mentioned option, the checkbox was back!

Monday, July 09, 2007 12:33:00 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, July 05, 2007

Coming from MySQL and PostgreSQL background I am used to tools such as mysqldump for getting a complete dump of an SQL database into an a file. The file then contains SQL commands for creating the database structure and more importantly, for filling it with data using INSERT statements. A nice feature indeed.

Since I've begun working with Microsoft SQL Server, it has always been a problem for me to get the same result. There is no command line utility that I know of that comes with SQL Server 2000 that allows you make the same dump as mysqldump provides. There is however a hidden feature in the Enterprise Manager that you can use to achieve the more or less same result as with mysqldump. I have written about how to get the database schema using Enterprise Manager some time ago. The problem is that it does not work for SQL Server 2005 - there is no Enterprise Manager for v2005! The Microsoft SQL Server Management Studio does not have that useful feature so we are left alone... Or maybe not.

Some time ago I was determined to find a solution for this problem. So I have searched high and searched low, and I have found something. The thing is the Database Publishing Wizard. It does exactly what is needed - it dumps the schema, the data and even stored procedures if any are available! It has a command line interface, a GUI interface and on top of it it integrates with Visual Studio!

What more can you want?

kick it on DotNetKicks.com

Thursday, July 05, 2007 10:19:44 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Wednesday, July 04, 2007

Following my last article on creating specialized validators, below I present the EmailValidator control which validates user input with a pattern of an email:

public class EmailValidator 
    : RegularExpressionValidator
{
    public EmailValidator()
    {
        ValidationExpression = 
        @"^[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]@
        [a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.
        [a-zA-Z][a-zA-Z\.]*[a-zA-Z]$";
        ErrorMessage = "Email is incorrect";
    }
}
Note that ValidationExpression is broken so it may be better displayed in the browser. As for how accurate, the expression is. It was taken from the Regular Expression Library page and I have had no problems with it.

Usage on a page after registration:

<my:EmailValidator runat="server" ID="EmailCorrect" 
    ControlToValidate="Email" />
Wednesday, July 04, 2007 6:03:19 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Validation controls are one of the best features that ASP.NET has to offer. They allow us to perform both client and server side validation and work very well well with the Control model that is given to us by the Web Forms model. Here I will describe how to use RegularExpressionValidator so that never again will you be searching for that email matching regular expression on all of your pages.

Usually when you use a RegularExpressionValidator you just drop it on a form (or code it by hand) and set few properties. Among them, there is the ValidationExpression. When done, it looks more or less like this:

<asp:RegularExpressionValidator runat="server" 
    ID="OnlyNormalLetters" 
    ControlToValidate="Login" 
    ErrorMessage="Login contains illegal characters" 
    ValidationExpression="[a-zA-Z]" />

As I have described in my article on the best practices of inheriting controls, it is a good idea to limit the number of times important things are repeated in the code. In case of RegularExpressionValidator, the important thing that gets repeated is of course the ValidationExpression property.

To avoid repeating the same expression on each page that requires it, it is better to create a new class that inherits from RegularExpressionValidator. In this class set the RegularExpression property to some constant string like on the following example:

public class NormalLettersValidator 
    : RegularExpressionValidator
{
    public NormalLettersValidator()
    {
        ValidationExpression = "[a-zA-Z]";
    }
}

And that's it. Using this validator is the same as using the built in one, but you don't need to provide the same ValidationExpression any more. Just register it in either web.config file or on the page and you are good to go.

Of course the example is very simple, but I hope it demonstrates a useful concept.

kick it on DotNetKicks.com

Wednesday, July 04, 2007 5:55:43 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Everyone knows the using statement. The statement that deals with IDisposable interface for us in a clean to write way. There is however one feature of this statement that is almost never mentioned. The feature I'm talking allows for multiple objects initialization of variables. Usage looks as follows:

using (SqlConnection conn1 = new SqlConnection(), 
    conn2 = new SqlConnection())
{

}

This way, both conn1 and conn2 will be disposed - no need to write 2 nested usings.

There is a note about this feature on MSDN but I've not seen it mentioned anywhere else.

Wednesday, July 04, 2007 8:34:02 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  |