Tuesday, July 03, 2007

I cannot remember how many times I was entering the same piece of code over and over again with few (if any) changes. The piece of code that I'm talking about is an event handler method with a signature similar to the following:

protected void Accept_Click(object sender, EventArgs e)
{
    //....
}

The whole structure is method is usually the same. We have access modifier, a name of an object, an underscore, a name of an event and finally the sender and EventArgs part of which only three things tend to change.

Keeping this in mind I have created a code snippet that saves me a lot of time when I need to create event handlers manually (which usually happens when working with ASP.NET controls).

Some time ago I have written an instruction on how to use code snippets and also I have provided a couple of useful snippets. The new snippet added to the collection is used by typing "eventh" and it allows for customizing 3 parts of an event handler that are most likely to change.

kick it on DotNetKicks.com

Tuesday, July 03, 2007 10:01:48 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 

While working with some obscure Microsoft's technology called MPS (Microsoft Provisioning System) I've been presented with one of the best error messages ever: "The server is unwilling to process the request.". So now we have to ask servers if they are willing to help us? Huh?

Tuesday, July 03, 2007 6:36:13 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Today I have found a really useful class inside the System.Diagnostics namespace. It's called DebuggerTypeProxy and it allows you to customize how you types behave (or more precisely what data do they present) inside the debugger.

Often I have overwritten the ToString method just to get my type look nice in the debugger. A common problem is when there is some kind of collection of objects and the only thing that you see when you look at it is the all of them are of a certain type. That's because of the default implementation of the ToString method. If you overwrite it to return - say a Name property of you Client object, you immediately have it easier when it comes to finding the concrete instance on the list. Although DebuggerTypeProxy won't help in making you types more easily visible on the list, it can do so much more!

Basically DebuggerTypeProxyAttribute is just what the name suggests - a proxy. It is a kind of view that you can assign to your types and debugger will use it much like DebuggerVisualizerAttribute is used to provide a custom view over a data type.

A simplest possible example to demonstrate how to use DebuggerTypeProxyAttribute:

[DebuggerTypeProxy(typeof(MyTypeProxy))]
class MyType
{
}

class MyTypeProxy
{
    MyType type;
    public MyTypeProxy(MyType type)
    {
        this.type = type;
    }
    public string Hash
    {
        get { return type.GetHashCode().ToString(); }
    }
}

And result of the code turns this:

Into this:

It is highly unlikely the you would ever need to create a type proxy to display it's HashCode, the example demonstrates a concept and that is: exposing method calls as properties. Normally debugger won't show you values that result from a method call. You can access them manually by calling methods in the Watch Window, Quick Watch Window or even Immediate Window. Using DebuggerTypeProxy you can achieve a more debugger friendly access to those results (if you ever need them).

kick it on DotNetKicks.com

Tuesday, July 03, 2007 5:51:40 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, June 29, 2007

Today while I was working on my usual solution inside Visual Studio I have encountered a serious problem with how Visual Studio, SourceSafe and Web Site projects interact. My solution that I was working with consists of several projects including few Web Sites. My environment is configured to use SourceSafe database as a version control system. Nothing unusual - a 100% Microsoft only environment. I had been working like this without any changes to the configuration for a long time but I noticed that no matter what I do, my solution file (.suo) is growing larger and larger...

Since .suo (solution user options) files only contain information about my options e.g.: opened files, break points etc I thought that it will not hurt much if I just delete this file. I didn't care about opened files nor the location of breakpoints. Besides, sometimes deleting the .suo file is just the only option to restore Visual Studio to a working state after it refuses to open a project file. On top of this, I have deleted the .suo file many times before without any negative effect. So I did again, but this time I was hit right between the eyes and I'm still recovering from the blow.

After deleting the file and starting the solution I got the following message:

"The Open from Source Control operation is still in progress but you can start working now. The rest of the projects will be retrieved asynchronously."

I thought, oh... OK, the message was not a warning and there are a lot of useless messages in Visual Studio so there is no need to worry. I was WRONG, but it came out some time later.

Everything opened correctly and it even seamed to work, but the pages looked different from what I was expecting. They looked exactly the same way as before I made my last changes that I didn't commit before the deletion of .suo file.

After a bit of investigating and testing I have found the problem. And the problem that is! It appears that if you have a file checked out inside of the Web Site project than the fact it is checked out is somehow remembered inside the .suo file. If you delete a .suo file then Visual Studio will try to be "smart" and will get the latest version of that file from the source control - SourceSafe in this case. What this means of course is that any changes in the checked out file will be lost WITHOUT ANY chance to stop and WITHOUT ANY warning message!!!

This issue is only a problem for Web Site projects. Other project types like Class Library are not affected. Now the questions are obvious: why Visual Studio is using .suo files to keep tract of what is checked in and what is checked out inside Web Site projects? Are .scc and .vspscc files not enough? Why would it even try to get the latest version? Is the fact that the file on the disk is not Read Only and is different from the version in the Source Safe not enough to at least issue a warring/question?

In my opinion it is obviously a bug and it has just caused me to lose half a day of work!

Friday, June 29, 2007 1:52:19 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Monday, June 25, 2007

Almost every time I'm working on an ASP.NET project I create a Visual Studio solution that consists of at least two projects: the web project and a class library. The first one is obviously needed. As for the second, what I put there include all kinds of ASP.NET related classes such as the BasePage class or just custom controls. This makes it easy to use those controls since Visual Studio (usually) automatically adds them to the Toolbox.

There are times however, when I need to make something quick. Perhaps a small project to test a new idea. In those cases, I rarely go for the 2+ projects solution layout since Visual Studio is standing in my way a bit - i.e. by hiding the possibility of adding new project to an already existing Web Site project (solution node is not visible on the tree view in Solution Explorer, but it is still possible to add the project using File menu). So I end up with only one project and the App_Code folder.

Working with App_Code is not a problem as long as you don't need to make some configuration in the Web.config file. Some elements require you to specify a type name. Normally in such a case, you need to provide a valid type format name in a form of <typename>,<assemblyname>. As long as you know the assembly name it's OK, but wait! There is no explicit assembly for App_Code. There is however an assembly behind the App_Code directory. It is simply called App_Code!

That said, it is usually enough to just specify the type name, without assembly name, for types defined in the App_Code directory.

So what about controls? In order to work with a control defined in App_Code directory we need to either register it on a page or in a Web.config file. There is however one issue. In order to register a control in a Web.config we need a namespace. By default however, neither pages nor classes added to an App_Code folder have a namespace. This is only a minor inconvenience because ASP.NET does not prevent us from adding a missing namespace declaration to a class in an App_Code directory. By adding such a namespace to a class representing ASP.NET Control, we can then add a registration in a Web.config file like the following one:

<pages>
  <controls>
    <add namespace="MyControls" tagPrefix="m"/>
  </controls>
</pages>

Notice that assembly attribute is not required.

For working with code, there is also a special class that helps with issues arising from the fact that there is no explicitly assembly nor a namespace for types in an App_Code directory. If at any time, there is a need to work with a type object of a class from the mentioned directory, .NET framework offers us a class called BuildManager which defines a GetType. Using this method it is possible to get an instance of a type object by providing just a name of a class defined in the App_Code directory.

kick it on DotNetKicks.com

Monday, June 25, 2007 6:17:51 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, June 20, 2007

After reading my article on recursive properties of ASP.NET controls, where I point out that not all properties are recursive, I have decided to fix one annoying behavior. The problem is that one of the most important property of all, the EnableViewState property is not recursive. This of course makes it useless in most scenarios. Never will we be able to rely on it while authoring our controls since ViewState can be disabled on any of the parent controls thus preventing our control from saving its state.

To solve this a very simple method can be used to check for the state of EnableViewState property:

public bool IsViewStateEnabled(Control control)
{
    if (control.Parent == null)
    {
        return control.EnableViewState;
    }
    return control.EnableViewState && 
        IsViewStateEnabled(control.Parent);
}
Wednesday, June 20, 2007 7:44:05 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, June 19, 2007

ASP.NET, or more accurately Web Forms, offer us a completely new way to create web pages. We can now work with control just like Windows developers. We even get to use an event driven model. How make best use of this? Below I present a useful pattern that I'm almost always following while working with ASP.NET.

Suppose that you are building a web application with lots of pages and forms for data input. On those forms you typically have input fields in form of TextBoxes, DropDownLists etc. Usually there are also some buttons that allow for invoking actions. Those actions include things like "Add", "Update" or "Cancel".

The standard way to create a form for inputing data would be to use mentioned before standard ASP.NET controls. That is fine. It gives us access to all that ASP.NET Web Forms can offer in terms of Page structure and event model. There is however one issue. In most cases there we will be several pages with the same buttons on them. Take for example the "Cancel", "Add" or "Update" buttons. Almost every time there is a data to be edited, there will be those buttons. If we use the "out of the box" approach, we end up with code similar to the following, on lots of pages:

<asp:Button ID="Add" runat="server" Text="Add" />

At first glance, there is not much wrong with it. If you look closer however, we can see the potential problems. One of the is certainly the Text property.

Why is it a problem? Suppose that now we need to localize the application? In this case, we will have to make a change in many places. Simple technique would be to decorate the Button control with attributes used by the Localization feature of ASP.NET like meta:resourcekey. But still we end up with one major problem: every time a change is required (that cannot be dealt with using Localization, Skins or other built in feature), we have to make it in many places. As we know: change in many places is a BAD PRACTICE.

What if we find out, that our add buttons need to have some special CssClass attribute? What if all our "Cancel" Buttons should have CausesValidation property set to false? Once again: a change is required in many places - which is ... BAD PRACTICE!

For localization, we can add an implicit localization attributes as mentioned above. What about CausesValidation or CssClass properties? Some of them we can try to set using Skin files, but as you will sooner or later discover, theming support in ASP.NET is VERY limited, especially when it comes to localization. You cannot localize skin files, some of the properties are not themeable etc. There are many examples of potential problems but what is a solution? It seams that there has to be a better way.

In my practice I have found that it is usually good not to use the standard controls that come with ASP.NET but rather make new ones that directly inherit from them. Doing so we inherit all the functionality without loosing anything (almost). As an example, take the aforementioned "Cancel" button. If we create a new control like this:

public class CancelButton : Button
{
    protected override void OnInit(EventArgs e)
    {
        Text = "Cancel"; // get value from resource
        CausesValidation = false;
        base.OnInit(e);
    }
}

And on pages, instead of the standard button, use this new control:

<my:CancelButton ID="Add" runat="server" />

In doing we allow ourselves to make changes in one place that will affect the whole application. In this way, without much work, we have gained a lot of flexibility for the future and saved a lot of potential work. If some time in the future, we need to localize the Text property for all Cancel buttons, we can do it in just one place which is a GOOD PRACTICE.

Benefits do not end there! If some day, there is a requirement, that all buttons should now be LinkButtons instead of normal Buttons we can easily do it bu just changing the base class from which our CancelButton inherits and the same technique can be used with other controls too (as long as their public interfaces match at least in naming).

Now the question is if you should always use the inherited controls. As usual, there is no simple answer to that question. There is a cost of having a lots of additional classes in the project if we try to follow this rule. Imagine that just for standard buttons, there will be quite a few: Add, Cancel, Remove, Back, Change, Edit just to mention some of them. For small, fast'n'dirty projects it will of course be a huge overkill (or will it?), but if you know that the project is not a small task, it is, in my opinion, a thing that should be seriously considered.

kick it on DotNetKicks.com

Tuesday, June 19, 2007 8:32:37 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [4]  | 

I'm a big ASP.NET lover mostly because of the fact that I can work with HTML in a more abstract way presented to me in form of controls. While authoring controls, it is always my goal to write as little HTML code as possible. To make it possible I relay heavily on composite controls. Sometimes however it is not possible or simply to complex to achieve a result using a composition of controls. That's where the Render method comes in handy.

Using Render method and accompanying HtmlTextWriter object we can write plain HTML using writer.Write() method. This however forces us to write HTML which I try to avoid. Here also the  HtmlTextWriter offers some alternatives that include writer.RenderBeginTag() method and HtmlTextWriterTag enumeration. Using them, we can generate HTML in a way that allows for some degree of compile time checking and some enhancements. If we just used the following code:

writer.RenderBeginTag("h1");

there is little that protects us from misspelling the tag name. There is also no way for a RenderBeginTag method to help us adjust the output to target concrete platform. We are simply telling it to write "h1" element and so it does because we expect it to. Consider however an alternative version:

writer.RenderBeginTag(HtmlTextWriterTag.H1);

This time, instead of passing "h1" string literal, we pass a value of a HtmlTextWriterTag enumeration. Now we are suggesting that we need the H1 element, but we leave a space for interpretation. What the writer object renders is up to it. Keep in mind however that HtmlTextWriter class and moreover the XhtmlTextWriter class are there to allow for customization. If there is a device that requires all tags to be uppercase, than it can be done using a special writer object that knows and targets the concrete device.

One thing that I only recently discovered however is how to write a "<br />" without writing "<br />". If we try to use the mentioned overload like this:

writer.RenderBeginTag(HtmlTextWriterTag.Br);
writer.RenderEndTag();

We will get an invalid HTML:

<br>

</br>

The solution is to use the writer.WriteBreak() method. It will output the required form of "<br />" and shield us from using plain text.

You may ask if it really matters. True, it is a very thin line of abstraction here but I like it this way.

kick it on DotNetKicks.com

Tuesday, June 19, 2007 7:22:24 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, June 18, 2007

With the release of .NET Framework 2.0, we have gained access to a very powerful feature called Anonymous Methods. I'm sure that almost any .NET developer has used Anonymous Method at least once and most of us use them on a daily basis.

Typically you use Anonymous Methods when you want to declare an event handler inline, without the need of creating a separate, named method (hence the name Anonymous). Other usage areas include delegates of types such As Predicate or Action. Mentioned delegates are most often used in methods found on all types of collection related classes be it Array or List<T>. Typical code for this may look like this:

string[] urls = GetUrls();
string[] urlWithWww;
urlWithWww = Array.FindAll(urls, delegate(string url) 
{ return url.StartsWith("www"); });

Nothing unusual here. The usefulness of Anonymous Methods comes from the fact that they allow us to access variables defined in the scope in which the very method is defined. Here as an example of how this feature is usually used:

string pattern = ".com";
string[] urls = GetUrls();
string[] urlWithWww;
urlWithWww = Array.FindAll(urls, delegate(string url) 
{ return url.Contains(pattern); });

Great feature indeed, but there is one gotcha that we have to be aware. The problem most often appears when we start to work with multiple threads. Given the following code:

foreach (string url in urls)
{
    DoSomethingAsync(delegate() 
    { 
        Debug.WriteLine(url); 
    });
}

We have to know that the url variable that we pass to a Debug.WriteLine method is "shared" among all Anonymous Methods and because of this, we may (and most probably we will) get results that we do not expect: same url printed few times, than a different url, again printed few times. Confusing, isn't it?

Why is that? Brad Adams explains the mechanism behind this strange behavior here (scroll down to the comments). It's worth mentioning that you could get the same strange behavior without working with multiple threads. It is just far more common to get it while theading.

To make things more "predictable", the code above has to be written in a slightly different way:

for (int i = 0; i < urls.Length; i++)
{
    string url = urls[i];
    DoSomething(delegate() 
    { 
        Debug.WriteLine(url); 
    });
}

Now every Anonymous Method gets its own copy of url and everything works as expected.

kick it on DotNetKicks.com

Monday, June 18, 2007 6:39:58 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

While working with ASP.NET, from time to time, I need to change some parameter that is common to all controls of on a page. An example of such operation might be setting ReadOnly property for all TextBox controls etc.

Below is a sample method code I use to get a flattened hierarchy of controls on a page:

public static Control[] FlattenHierachy(Control root)
{
    List<Control> list = new List<Control>();
    list.Add(root);
    if (root.HasControls())
    {
        foreach (Control control in root.Controls)
        {
            list.AddRange(FlattenHierachy(control));
        }
    }
    return list.ToArray();
}

As you can see, it is pretty simple. The method recursively traverses control hierarchy and collects each control it finds on its way to a collection which is finally returned to the caller in a form of an array.

As mentioned above we can use this method to set the ReadOnly property of all TextBox-es on the page. To do this, a code similar to the one below can be used:

private void MakeTextBoxesReadOnly()
{
    Control[] allControls = FlattenHierachy(Page);
    foreach (Control control in allControls)
    {
        TextBox textBox = control as TextBox;
        if (textBox != null)
        {
            textBox.ReadOnly = true;
        }
    }
}

Using a combination of the above outlined methods it is easy to implement a kind of ReadOnlyMode page filter. Just identify what controls need to be ReadOnly and how to make them so (RadioButton for example doesn't have a ReadOnly property). When you know how and what you want to make ReadOnly, just override Page's OnPreRender method by adding a call a MakeTextBoxesReadOnly method (or whatever method you create).

Of course all of this is possible thanks to the great ASP.NET control model which is one of the things that I really like about ASP.NET.

kick it on DotNetKicks.com

Monday, June 18, 2007 11:07:38 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [3]  |