Monday, January 25, 2010

Microsoft recently release it's Search Engine Optimization Toolkit as part of the Internet Information Services. Making SEO Toolkit part of IIS is a strange decision to start with, and reasons for that are beyond me. To work around this "issue" I've invested some time to make it possible to use the same functionallity online via a web application. So with no further adieu I present to you the Search Engine Optimization Tools - Online.

SEO Tools I just made available is a first step in building a comprehensive workshop for professional web developers who are not pro at SEO.

Comments are welcome!

Monday, January 25, 2010 1:09:59 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Wednesday, May 21, 2008

Just few days ago, my friend at work found a peculiar error message in ASP.NET RangeValidator control. He was trying to validate length of a string in a TextBox. Controls on page definded as follows:

<asp:TextBox runat="server" ID="TB" />
<asp:RangeValidator runat="server" ID="RV" 
MinimumValue="3" MaximumValue="20" 
ControlToValidate="TB" Type="String" />

What he got was a best error message ever:

"The MaximumValue 20 cannot be less than the MinimumValue 3"

That's right! 20 cannot be less than 3!

Interesting isn't it?

I made some research of my own and I've found out that sane people should not look inside RaneValidator's (and other related classes) code! What it does inside is it uses a String.Compare to check if ranges are ok.

Of course, the problem are not the ranges, but the Type property of a validator. If set to String, it treates minimum and maximum values as strings and compares them as such - meaning that it compares character by character instead of just number to number.

That explains, why my friend got the error, but it certainly does not justify the text of the message! It might take long hours for an inexperienced developer to find where the problem lies. Come on Microsoft! You can do better than that!

Funny thing is that I never even thought about using RangeValidator to ensure string length, but suggested RegularExpressionValidator right from the start :-).

Wednesday, May 21, 2008 7:44:48 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [5]  | 
 Saturday, May 17, 2008

As we all know, ASP.NET uses one form model to do all it's magic. Love it or hate it, we have to live with it. 99% of the time, it is not a problem, but then there is this 1%...

The main problem with ASP.NET's model is that the form tag has a fixed action attribute. What if we want to change it? No, there is no simple way of doing it. Solutions vary. Most common one is to create your own FormControl that inherits from HtmlForm and override RenderAttributes method. Unfortunately, inside that method, we have to do everything the original method does and only change the action attribute to the desired value. Ugly!

Another one is to provide an OutputFilter for the Response but that is also a lot of coding.

My preferred way of dealing with this issue is to provide my own, special HtmlTextWriter. Its role is to intercept the WriteAttribute method call and provide my own value. Following code illustrates the concept:

class ActionAttributeWriter
    : HtmlTextWriter
{
    string action;
    public ActionAttributeWriter(
        HtmlTextWriter writer, string action)
        : base(writer)
    {
        this.action = action;
    }
    public override void WriteAttribute
        (string name, string value, bool fEncode)
    {
        if (name == "action")
        {
            value = action; 
        }
        base.WriteAttribute(name, value, fEncode);
    }
}

Only thing that is needed then is to use this writer instead of a normal one. Page.CreateHtmlTextWriter can be used for this purpose:

protected override HtmlTextWriter 
    CreateHtmlTextWriter(System.IO.TextWriter tw)
{
    ActionAttributeWriter writer = 
        new ActionAttributeWriter(
            base.CreateHtmlTextWriter(tw), 
            "action");
    return writer;
}

Solution is not very clean and I would certainly not recommend it for a public product, but it's better than nothing.

Saturday, May 17, 2008 2:09:17 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [4]  | 
 Wednesday, September 05, 2007

While working with any kind of configuration files in .NET, be it Web.config in case of ASP.NET or App.config in case of Windows Forms applications, we very often use the appSettings section. We use it to store all kinds of simple configuration options. Options, that are too simple for us to implement a completely new SectionHandler type. There is however one problem with appSettings section not very expressive.

What does it mean to be expressive? Consider the following example:

<appSettings>
  <add key="source1user" value="user" />
<add key="source1password" value="pass" /> </
appSettings>

In simple cases, it may be acceptable, but what happens if more user keys are required for some reason? Maybe we need to access few different locations, each of which requires a username and password? We may use some kind of prefix for each key like in the above example, but that is not very elegant. What is key and value anyway?

Another obvious problem here is when we need to have 2 parameters associated with a single logical functionality in the application, we need 2 entries in appSettings section.

If we still don't want to implement a new SectionHandler type, we have very nice option left: SingleTagSectionHandler.

MSDN describes it as: "Handles configuration sections that are represented by a single XML tag in the .config file". And that's about it. Unfortunately, (as usual) MSDN provides no example of how to use it. Fortunately it is quite simple:

<configSections>
  <section name="remoteDataSource" type="System.Configuration.SingleTagSectionHandler" />
</configSections>

<remoteDataSource username="user" password="pass" url="http://remote/" />

Using the newly declared section from the code is also easy:

Hashtable remoteDataSource = 
(Hashtable)WebConfigurationManager.GetSection("remoteDataSource");
string username = (string)remoteDataSource["username"];
string password = (string)remoteDataSource["password"];
string url = (string)remoteDataSource["url"];

Simple, yet useful.

kick it on DotNetKicks.com

Wednesday, September 05, 2007 8:45:40 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [6]  | 
 Thursday, August 09, 2007

OnClientClick is a useful property introduced in ASP.NET 2.0 that allows us to add some client-side behavior to button control. Using is as simple as providing the script to be called when a button is clicked by a user:

<asp:Button runat="server" ID="Save" 
    OnClientClick="return confirm('Are you sure?');" />

The problem is that if you use it like that, client-side validation won't fire. Looking at the rendered HTML quickly explains the situation:

onclick="return confirm('Are you sure?');WebForm_DoPostBackWithOptions(...)"

As you can see, the validation doesn't even have a chance to fire (which happens when WebForm_DoPostBackWithOptions is called).

Solving the issue is simple (or not). All that has to be done is a little change in our OnClientClick script (a piece of code found somewhere on the Internet):

<asp:Button runat="server" ID="Save" 
    OnClientClick="if (!confirm('Are you sure?')) return false;" />

Now we only return false (preventing the submit) in case a user didn't confirm the action, otherwise, the rest of the script will be called thus firing validation.

The reason I said that it may not be a simple issue is the fact, that the validation happens AFTER the confirmation, which is not the best thing in my opinion. Why ask the user about saving his data if there are still errors on the form, of which we will inform him after he confirms that he wants to save it?

After analyzing a bit, the code responsible for dealing with OnClientScript, I have come to a conclusion, that solving this problem is not an easy task. It would require some dirty hacks on the server side to make it pretty or calling validation routines on the client, before displaying the confirmation dialog (keeping in mind that checking if there are validation routines present at all is necessary in this case).

I've just left it as it is. After all it's only a minor inconvenience - at least in my case.

Thursday, August 09, 2007 10:38:51 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [5]  | 
 Tuesday, August 07, 2007

ASP.NET Ajax comes with a nice way to attach to a load event of a page. To do it just call Sys.Application.add_load and pass it a function as an argument. Done. Everything works as expected... WRONG!

It comes out that add_load fires on each callback and not only when the page loads for the first time. That is of course a problem if you want something to happen on page load only.

From what I've been able to learn, this behavior is by design. Although it is never mentioned in a strigh forward way in a description:

"Raised after all scripts have been loaded and after the objects in the application have been created and initialized."

There are some places in the documentation, that suggests that this is a way it was intended to be. First of all, ASP.NET Ajax tries to mimic that ASP.NET Page life cycle and as such, fires the load event every time there is a callback. The other thing that makes me believe, that load's behavior is there by design is this:

"You can use the event arguments to determine whether the page is being refreshed as a result of a partial-page update and what components were created since the previous load event was raised."

So now I know, but I still cannot accept the naming convention. Sys.Application plainly suggests, it's a kind of singleton, and not a per load thingy.

Tuesday, August 07, 2007 12:18:19 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [4]  | 
 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 [5]  | 
 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 [9]  | 
 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 [4]  | 
 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 [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 [2]  | 

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]  | 
 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 [1]  | 
 Monday, June 18, 2007

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]  | 
 Tuesday, June 12, 2007

Today I've got a question if it is possible to make ASP.NET not to render the div tag around it's special hidden fields (i.e.: "__EVENTTARGET"). I have never thought about it before, so I didn't know the answer. I had to investigate. After a brief overview of the state of things, I have come to believe that there is no easy way to do achieve this. To confirm my suspicions I used the Reflector.

I have found that it is indeed possible to make ASP.NET not render the div tag if RenderDivAroundHiddenInputs property of HtmlTextWriter class returns false or if LegacyRendering is enabled. You can enable the later by setting xhtmlConformance mode to Legacy in Web.config file. Unfortunately the RenderDivAroundHiddenInputs property of HtmlTextWriter class always returns true and you cannot change it because it is internal. Additional investigation has shown that there is a class that overrides that property to return false. The class was: XhtmlTextWriter.

How to make ASP.NET use XhtmlTextWriter instead of normal HtmlTextWriter? I was unable to find a way to configure ASP.NET to do it. Setting xhtmlConformance mode to strict doesn't help. Google also is not very helpful. The only way seams to be either override Render method of a Page class like this:

protected override void Render(HtmlTextWriter writer)
{
    base.Render(new XhtmlTextWriter(writer));
}

Or better yet to override the CreateHtmlTextWriter like this:

protected override HtmlTextWriter CreateHtmlTextWriter(System.IO.TextWriter tw)
{
    return new XhtmlTextWriter(base.CreateHtmlTextWriter(tw));
}

This however requires you to use a kind of BasePage class for each page in your project (which is good, but not everyone likes it). Another concern I have is the fact that there is very little information on XhtmlTextWriter class, and the one that is available seams to suggest that the class is meant rather for mobile devices.

There is one more way you can try to solve the problem. You can use Response.Filter to do the job, but I would not recommend it unless you really, REALLY need to get rid of the div. Creating such a filter can really hurt performance. If you decide you REALLY need to, Mads Kristensen has an example of how to make a filter. He is using Response.Filter to move ViewState to the bottom of the page.

kick it on DotNetKicks.com

Tuesday, June 12, 2007 8:53:08 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [7]  | 

In my last article, I have described a "feature" of some of the properties of ASP.NET controls: recursive properties. It is obvious why it is important to know about it, but how does it impact the development?

Imagine that you need the following functionality: Page with on it controls and among them, there is a panel containing buttons such as Save, Cancel etc. This panel is inside some kind of container control - like div tag. The goal is to detect if there is at least one visible button inside the container. If so, render the container, otherwise, containing div should not be rendered at all.

<div runat="server" id="ActionPanel">
    <asp:Button runat="server" ID="Save" />
    <asp:Button runat="server" ID="Cancel" />
</div>

The code to accomplish this is "easy". Get the reference to the div control (which was made to runat="server"). Iterate over its child controls and for each control, that was a Button, check its Visible property. If at least one of the property returns true, the div should also be visible. Sample code to achieve this:

protected override void OnPreRender(EventArgs e)
{
    ActionPanel.Visible = GetActionPanelVisibleStatus();
}
private bool GetActionPanelVisibleStatus()
{
    foreach (Control control in ActionPanel.Controls)
    {
        if ((control is Button) && (control.Visible))
        {
            return true;
        }
    }
    return false;
}

I'm using a loop over all child controls to make it more generic.

The only problem is that above implementation does not work in some cases. The problematic situation only occurs if the div's Visible property is set to false. Once invisible, it stays that way with no way of going back to visible state! Why is that? Of course it is because of the recursive nature of Visible property. With this in mind it is easy to fix the problem by setting Visible property of the container control to true, before processing it's child controls:

protected override void OnPreRender(EventArgs e)
{
    ActionPanel.Visible = true;
    ActionPanel.Visible = GetActionPanelVisibleStatus();
} 

Makes sense?

Gathering it all up, it is now easy to build a self-hiding ASP.NET control (or UserControl). Just remember about recursion!

kick it on DotNetKicks.com

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

One of the other days I encountered a strange problem. I was unable to set the Visible property of one of built in ASP.NET controls to true. I had verified that it is indeed true that I'm passing as a new value for the property. I had even used the Watch and Immediate Windows to set that value - nothing worked. I had decided to see what is going on and so I looked at the source code of the Control's Visible property...

What I have discovered is that the Visible property is in fact a recursive property! What does it mean? In short, the Visible property will only be true if the Parent's Visible property is true which in turn will be true if... and so on, up to the top of the control hierarchy. No a bad idea after if you think about it.

This feature obviously has some impact on how everything in ASP.NET works. As an example take a look at the following code:

Control parent = new Control();
Control child = new Control();
child.Visible = false;
Response.Write(child.Visible + "<br />");
child.Visible = true;
Response.Write(child.Visible + "<br />");
parent.Controls.Add(child);
parent.Visible = true;
Response.Write(child.Visible + "<br />");
parent.Visible = false;
Response.Write(child.Visible + "<br />");
child.Visible = true;
Response.Write(child.Visible + "<br />");
parent.Visible = true;
Response.Write(child.Visible + "<br />");

What would you expect the output to be? Below is the output generated by the above code.

False
True
True
False
False

True

The marked values are not so obvious, but if we take into consideration, the fact that the Visible property is recursive, everything starts to make sense... or does it?

At first I thought that there should be more of those type of properties. It makes sense for a Visible property to be recursive since if we do not render a parent, we won't render a child. Why then, wouldn't the other, well known and widely used property: EnableViewState work in a similar way? If we repeat the same experiment we will get a different set of results:

Control parent = new Control();
Control child = new Control();
child.EnableViewState = false;
Response.Write(child.EnableViewState + "<br />");
child.EnableViewState = true;
Response.Write(child.EnableViewState + "<br />");
parent.Controls.Add(child);
parent.EnableViewState = true;
Response.Write(child.EnableViewState + "<br />");
parent.EnableViewState = false;
Response.Write(child.EnableViewState + "<br />");
child.EnableViewState = true;
Response.Write(child.EnableViewState + "<br />");
parent.EnableViewState = true;
Response.Write(child.EnableViewState + "<br />");

And results:

False
True
True
True
True

True

Notice, that this time we get what we set. Does it make sense? How is EnableViewState different from Visible? The functionality that depends on both of those properties only works if Parent works.

I'm not sure if there are more properties that work in a recursive way. I believe that it would be better if all properties worked that way which would make development more predictable. Unfortunately Visible is the only property that I know of that works in a recursive way, but there may be more. ASP.NET never stops to surprise me.

kick it on DotNetKicks.com

Tuesday, June 12, 2007 8:10:07 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [6]  | 
 Monday, May 14, 2007

I've been playing with ASP.NET Localization features lately and I have mixed feelings about it. I mean, the Localization features of ASP.NET are great, but you have to be very careful not to mess up.

Visual Studio 2005 allows for easy localization of a page or a control via the Tools->Generate Local Resource menu item. I have tried this one on the source view of the page (the view that I most often work with). The problem is that it does not work from this view!!! The error message is:

---------------------------
Microsoft Visual Studio
---------------------------
Source view does not support resource generation. Switch to design view to generate resources.
---------------------------
OK
---------------------------

Ooook. I thought that we have to separate presentation from logic but I suppose this is an exception from the rule. No wonder it was so hard to remove "the feature" of reformating the code after switching from source view to design view in Visual Studio 2003 if they have a code with such high quality. There is simply no separation between the model and the view so problems are to be expected.

So I have switched to the design view and on my sample page, with only a GridView with few collumns, everything worked fine. I've got the App_LocalResources folder and a Default.aspx.resx file in it and every localizable property was already in there. The aspx markup was also modified - meta:resourcekey attributes have been added to all relevant places. Nice? Not so, unfortunately :-(.

I have tried the same technique on a real page from a real project. On the page, there were a couple of my custom controls. Invoking the Generate Local Resource function on such a page made a lot of mess with the html/aspx code. Some controls have been added as inner controls etc. This is probably the very reason why cybercrypt15/glenn writes that you should not use the Generate Local Resource feature.

If you do all the work manually (wich is not such a big task after all - just add a meta:resourcekey attribute where necessary), you will find that Localization is really a nice feature.

kick it on DotNetKicks.com

Monday, May 14, 2007 9:40:29 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Friday, May 11, 2007

ASP.NET comes with a set of controls called "Validation Controls". Useful as they are, there are few features missing to make the picture complete. Some of the shortcomings have been fixed with the ASP.NET 2.0. This includes the ValidationGroup property. Some of the missing features I have described in my other articles: Validation Controls As Images - Take 2, Validation Control As Images - Workaround and Validation Controls Vs Control Adapters.

One thing that I have recently discovered missing from the set of features ASP.NET validation infrastructure provides was the way to perform initial validation of a page right after it has been downloaded by the browser for the first time. Imagine for example a form on a page where you instantly know which fields are required. Normally to do it, you would emphasize the labels of those fields in some way - probably by using a stronger/bigger font. I like not to repeat myself so I've tried to use the Validation Controls just for this. Instead of a bold label I wanted to have an ErrorMessage of each ValidationControl displayed for each field that requires validation.

After a bit of searching I have found no solution to my problem so, as usual, I have used my old mantra: "use the source Luk". What I have found is that it should be possible to do it so after few failed approaches I have found the way.

In order to perform initial validation on an ASP.NET page I have used a following JavaScript function:

function initialValidation()
{
    if (typeof(Page_Validators) == "undefined")
    {
        return true;
    }
    var i;
    for (i = 0; i < Page_Validators.length; i++)
    {
        ValidatorValidate(Page_Validators[i], "", null);
    }
}

I have put the call to this function in a body.onload event of an HTML page (the only place that I have found it to work).

The interesting thing is that if you are using ValidationSummary to display a summary of all errors on a page, it will not be shown after the initial validation. It will be shown if a user despite having the error message displayed near the input, tries to submit the page.

As a side note: don't forget to validate everything on the server-side! Do not trust the data that comes from the user!

kick it on DotNetKicks.com

Friday, May 11, 2007 1:58:04 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Tuesday, March 13, 2007

Every once in a while while working with ASP.NET there comes a time when you need to have a DropDownList with a fixed set of items. Or maybe the items are retrieved from the database, but still every instance of the control will have exactly the same items. How to do it efficiently?

Lets look at the simple example of a DropDownList with country names - the one you see on many pages. Wouldn't it be nice to have a reusable control for this?

The simplest way to create a Self Populating DropDownList is to inherit from the standard one, set the DataSource somewhere and call DataBind(). That is the tricky part.

If you have been working with ASP.NET for a while you are probably aware of the ViewState thingy. As good as it is, it can often make your page too large. This is specially true for DataBound controls. A simple Counties DropDownList would make your ViewState huge! So what can be done about it? Just disabling ViewState won't help because usually disabling it breaks some of the other parts of control's functionality.

Dealing with ViewState is simple once you get to know one very important thing. Only changes made after the Init phase of the Life Cycle are persisted to the ViewState! Or more precisely, changes only changes made after the control has started tracking ViewState (TrackViewState method has been called). It means that everything you put to the ViewState before that, will not be persisted. By default controls will have their TrackViewState method called right after the Init phase.

We can use this knowledge to our advantage. If we populate our DropDownList before or during the Init phase we will not affect ViewState. Doing so however has one drawback: we have to perform this operation on each request and not only when IsPostBack is false. This is not an issue if we use some kind of cache and we populate a lots of controls with the same data.

kick it on DotNetKicks.com

Tuesday, March 13, 2007 9:35:32 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Wednesday, March 07, 2007

Every ASP.NET developer knows (or at least should know) about the Life Cycle. Page has it's Life Cycle, controls have theirs Life Cycle (more or less the same as the one of the Page). There is a good article on MSDN regarding the Page Life Cycle. From it, you will learn that at any given moment, the Page and all controls are in the same "phase" of the Life Cycle, be it Init, Load, PreRender or Unload.

The interesting part about the Life Cycle is when it comes to dynamically added controls. The controls you add in code using Controls.Add call. Since controls also have the Init, Load and PreRender and Unload phases, what happens when we add a new control during a PreRender phase? As stated above, Page and all controls are always in the same phase. So what happens?

The same article explains this phenomenon and calls it "Catch-up". What it basically means is that at the time of adding a control to a Controls collection, the new control "walks" through all it's phases until it "catches-up" with the current phase of it's parent control (i.e. Page).

In order to better understand this, you can use the following example. On your page override an OnPreRender method and add a following code:

protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);
    Button b = new Button();
    b.Load += new EventHandler(b_Load);
    b.Init += new EventHandler(b_Init);
    b.PreRender += new EventHandler(b_PreRender);
    b.Unload += new EventHandler(b_Unload);
    Controls.Add(b);
}

You will also need to create the event handler methods. As the next step, put a break point on each of those handler methods and run the debugger to see what happens. You will notice that when control is added to a collection of Controls, it's events are fired immediately to catch up with the phase of its parent.

kick it on DotNetKicks.com

Wednesday, March 07, 2007 4:19:03 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Tuesday, February 20, 2007

After a while of thinking and struggling with Control Adapters I was unable to find a good solution to get my Validation Controls render as images. I have came to the following conclusions:

  1. Control Adapters will not help
  2. Overriding each Validator is not a good solution
  3. Creating my own Validation Controls is not a good solution

Given the above, I have once again looked at everything I have learned. I have looked at the html code rendered by the controls and then... solution came to me! It turns out that we don't need ASP.NET to get things working. ASP.NET stands in our way when it comes to handling this task, so why not use a plain old CSS? So I did.

When Validaton Control:

<asp:CompareValidator runat="server" ID="V" ControlToValidate="c1" ControlToCompare="c2" Text="Error Text" ToolTip="Title Text"></asp:CompareValidator>

is rendered on a page it looks more or less like this:

<span id="ctl00_V" title="Title Text" style="color:Red;visibility:hidden;">Error Text</span>

To make a nice image out of it, we need few things. First we need one tradeoff: we have to remove the Text attribute, otherwise it will mess the looks a bit. Next we decorate the server control with a CssClass attribute with a value such as "error". Next we create a style:

span.error
{
  display: -moz-inline-stack;
  display: inline-block;
  background-image: url(error.gif);
  background-repeat: no-repeat;
  height: 16px;
  width: 16px;
}

Notice in the style few things. First, we need the <span> element to be "inline-block". That is because we need it to have a height and width. Furthermore, FireFox does not support "inline-block" (!!!) but we can use a simple workaround with "-moz-inline-stack" value as described by Nicholas in Pain with inline-block article (also see the comments). By default span (inline element) will only be as large as the text it contain. Since in the proposed solution, there will be no text in the <span> this is needed. Next, we set the background-image to a desired url and set the width and height of an element. That's it!

The important thing to note here is the "inline-block" value for a display property. It is a CSS 2.1 introduced value and browser support may vary. After analyzing the display declaration article on quirksmode, I've came to a conclusion that it should be safe to use this technique. Internet explorer "supports" it. Firefox "supports" it. Opera supports it.

Yet again. ASP.NET stands in the way... If you try to use a Display="Dynamic" property, you will find that the proposed solution does not work with FireFox. After a close analysis I came to a conclusion that it works with IE only by chance. The problem is that the validation scripts used by Validation Controls set elements display property to "inline" in case Display property was set to Dynamic on the server control. Internet Explorer somehow manages to use the value from the style which is "inline-block" and so it works. FireFox uses the "inline" value and so we have an <span> element with no content - an invisible element.

I have currently few ideas of how to overcome this problem. One way it could be done is to put an absolutely positioned Validation Control inside a relatively positioned <div> element like this. Remove the Display="dynamic" attribute and mark the containing div with a class="error" and change the styles as follow:

div.error
{
  position: relative;
  display: inline;
}
span.error
{
  position: absolute;
  left: 0; top 0;
}

The positioning of elements needs some work, but hey at least it works!

Complete code here: ValidationControlsAsImages.txt (.54 KB)

kick it on DotNetKicks.com

Tuesday, February 20, 2007 9:57:25 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Monday, February 19, 2007

Once again I have gone through the process of customizing the way the ValidationControls are rendered in particular I need them to render an image. I have described a workaround of how to get them to render as images. The problem is that you have to tweak each validator that you want to use. In the same workaround, I have described, why it is not possible to use use Control Adapters to achieve the goal - the really important part that makes validation controls work is hidden in the Render method which is not called by the WebControlAdapter. Today I have learned that Render is called by the ControlAdapter class which is a base class for a WebControlAdapter. If we forget recommendation to use a WebControlAdapter for controls that inherit from WebControl we are almost there.

Almost... It makes a big difference. It turns out, that you cannot customize the element name if you use the ControlAdapter so you cannot change the default <span> element to an <img> element, but at least you can still get the Render method of BaseValidator to be called.

What is my opinion on the whole Control Adapters feature of ASP.NET 2.0? The idea was great. This is only a step in a direction where we should have begin and not end. I mean: why the a control needs to know how to render itself? Differently on different browsers. Differently, depending on the configuration, etc. Adapters make it all right. No longer controls have more then one responsibility. But that is only a try. Nice, but still only a try. The example of Validation Controls shows that once something is done wrong, it is very hard to make it right again. The same holds true for most of the existing controls. Just take a look at he amount of code in the CSS Control Adapters.

I only hope that in v.next some of the issues will be fixed. I know unfortunately, that it can only be a hope. There is a lots of code that would have to be rewritten and I don't suppose Microsoft will do it anytime soon :-(

Monday, February 19, 2007 1:45:43 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Saturday, February 03, 2007

There are couple of folders that have a special meaning in ASP.NET. Those folders include folders like App_Code where you usually put your code or App_Themes where you put themes. There is also an App_Data folder which "Contains application data files including MDF files, XML files, as well as other data store files" (MSDN).

From App_Data folder description it is obvious that it is where you should put your data. But how to do it? I have searched high and low for a methods or properties that help interact with this directory. The reason is because I don't like hard-coding strings in my code and I would have to hard-code at least one: "~/App_Data". I thought that since there are method to get the location of temp directory:

System.IO.Path.GetTempPath(); 

Or even to get the system direcotry:

Environment.SystemDirectory 

There should be a way to get the App_Data directory.

Apparently I was wrong. Unfortunately. There is no Strongly Typed method or property to get to the location of App_Data directory!

I have found 2 places in code where "App_Data" appears as a string (that's why I'm pretty sure there are no properties or methods). One place is a GetDataDirectory method in an internal System.Web.DataAccess.SqlConnectionHelper class and the other is in a SetUpDataDirectory method in a System.Web.HttpRuntime class.

My guess is that the first one is used for Membership Provider that by default uses Microsoft SQL Express database and App_Data directory to store the mdf files. The other one is probably not used at all - I have found no code that calls that method! 

When I have looked inside those methods I have found one thing that they have in common. Both set some data object in an AppDomain via:

AppDomain.CurrentDomain.SetData("DataDirectory"...) 

So I have made a test and used on one of my pages:

string dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory") as string; 

And of course it worked as expected. Unfortunately we cannot (or should not) use this kind of code since it is a dirty hack that relies on internal implementation of some internal classes and it also requires us to hard-code a string. So what's the benefit? The only one is that now I'm pretty sure, that there is no way to interact with App_Data folder using BCL so I will no longer have to search for it on the Internet - thing that I have done countless times.

kick it on DotNetKicks.com

Saturday, February 03, 2007 3:18:21 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [3]  | 
 Wednesday, January 31, 2007

In my last article on IsBindableType, I have desribed, why AutoGenerateColumns does not work for Nullable types. Now I present a solution for this problem.

In order for your GridView, FormView, or DetailsView to autogenerate the field for your Nullable<T> property you have to subclass the control you are using: say GridView and override the IsBindableType method. In this overriden method, you have to add a check to see if a type is Nullable. This can be done in a following way according to Yitzhak Gootvilig's post:

public static bool IsNullableType(Type type)
{
    return type.IsGenericType && 
      type.GetGenericTypeDefinition() == typeof(Nullable<>); }

Just put this code in some kind of reusable library since I have a feeling that ASP.NET controls will not be the last place you will need it :-)

A full implementation of IsBindableType after the additional check will then look more or less like this:

public override bool IsBindableType(Type type)
{            
    return NullableHelper.IsNullableType(type) 
      || base.IsBindableType(type); }

This simple hack has to be repeated for each of the *View controls. Fortunately it is not a common scenario where you have the AutoGenerateColumns property set to true :-).

kick it on DotNetKicks.com

Wednesday, January 31, 2007 1:50:07 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Today I have encountered a strange problem with GridView's AutoGenerateColumns property. The problem was that not all columns were generated automatically. It would not be a surprise if it happened for complex types such as my own, but I have noticed that simple (in my opinion) types such as Nullable<Guid> were also not generated! So I went investigating.

After a while of hacking and slashing through the GridView's code I have found the reason. It appears that columns are only auto-generated for properties whose type is a bindable type. What does that mean? Who decides if a type is bindable or not? I have continued my investigation and...

After a while I have found that there is a method on a GridView control called IsBindableType which looks like this:

public virtual bool IsBindableType(Type type)
{
      if ((!type.IsPrimitive && (type != typeof(string))) && 
      ((type != typeof(DateTime)) && (type != typeof(decimal)))) { return (type == typeof(Guid)); } return true; }

Apparently this method decides that Nullable<Guid> (or Nullable<int> for that matter) is not a bindable type! Because of this, you will not see properties of such a type automatically rendered in a GridView!

Being curious I have asked myself: why such a method is defined on a GridView control? Is it not a more general issue to decide if a type is bindable or not? So I went investigating even further.

I have found that there are 5 IsBindableType methods defined in System.Web.UI.WebControls namespace:

  • AdRotator
  • BaseDataList
  • DetailsView
  • FormView
  • GridView

Of those 5, DetailsView, FormView and GridView have exactly the same implementation. BaseDataList has slightly different:

public static bool IsBindableType(Type type)
{
      if ((!type.IsPrimitive && (type != typeof(string))) 
      && (type != typeof(DateTime))) { return (type == typeof(decimal)); } return true; }

Notice the static modifier! AdRotator on the other hand has exactly the same implementation as the BaseDataList but here the method is an instance method and is private!

So, we have basically 5 places in code, each of which implements the same logic, some do it differently and none does it correctly :-(.

kick it on DotNetKicks.com

Wednesday, January 31, 2007 1:28:45 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, January 16, 2007

In most of the ASP.NET projects I have been working on, I have needed a way to easily navigate to any page in the solution. To accomplish this I usually created some kind of User Control with links to all pages. If the project was small I usually entered the links by hand. For bigger projects I have used a Repeater control and filled it with data from the file system.
The method used to get the data from the file system looks more or less like this:

public string[] GetAllPages()
{
    int applicationFolderNumberOfCharacters = HttpRuntime.AppDomainAppPath.Length;
    List<string> pages = new List<string>();
    string[] files = Directory.GetFiles(
      HttpRuntime.AppDomainAppPath, "*.aspx", SearchOption.AllDirectories); return Array.ConvertAll<string, string>(files, delegate(string file) { return "~/" +
         file.Substring(applicationFolderNumberOfCharacters).Replace(@"\", "/"); }); }

On the Page or User Control the Repeater I use looks as follows:

<asp:Repeater ID="Links" runat="server">
   
<ItemTemplate>
      
<a runat="server" href='<%# Container.DataItem %>'><%# Container.DataItem%></a><br />
   
</ItemTemplate>
</
asp:Repeater>

If you put it on the Master Page, you will get access to every page from every page, which is great during development. Just don't forget to remove it from the production code.

kick it on DotNetKicks.com

Tuesday, January 16, 2007 7:38:57 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 

Today Mads shows us a not well known class that is called a Triplet. He also asks a question: how you would use it. Fortunately I have seen this class before so here is what I have learned:

Triplet is used in the same way as a Pair class - mostly in the LoadViewState and SaveViewState methods. Generally if you are saving view state in your control you not only have to store your data, but also the data returned by the call to the base.SaveViewState method. This is where the Pair class or the Triplet come in handy since given two (three) fields, one is used for the base control's state and the other can be used by your state. Similarly, when loading the state in the LoadViewState method you get your own state from one of the fields, and pass the other to the base class'es LoadViewState method. You have to remember to pass the same field you have used in the SaveViewState method or the things will go nasty ;-).

Triplet is used when Pair is not enough. If Triplet is not enough, you have to create your own class.

I hope this sheds some light on the topic.

Tuesday, January 16, 2007 6:55:47 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Thursday, January 11, 2007

It is a common practice in ASP.NET development to use controls provided by third parties. Such controls are usually distributed in form of an assmebly .dll files which you put into the Bin folder of your ASP.NET application. When using Visual Studio, you just add a reference to a file and the file is copied to that directory for you. What you don't get are new icons on the Toolbox representing newly added controls. You have to have to go to the Toolbox, select Choose Items... from context menu and point to the same dll file you have just used when adding a reference.

A much easier way to accomplish the same thing is to just do this second step though. By adding items to a Toolbox, Visual Studio automatically copies the required files into the Bin folder and by doing so, creates a reference to it so you don't have to.

When adding adding items to the Toolbox I usually prefer to create a separate Tab and add items there. For each group of controls I create a new Tab. The reason for this is that it is much easier to remove a whole Tab from the Toolbox than each individual item at a time. (You can also use the Choose Items... window to remove unneeded items, but I have found removing the Tab a lot easier and faster).

The third and in my opinion the best way of adding third party controls to a project is to create a separate project in the solution. In this project, for each control you want in your Toolbox, create a class and inherit it from this control. I have found that Visual Studio 2005 automatically adds to the Toolbox, controls that it finds in the Solution. An advantage of such an approach (other than that it is generally a good idea to always do so) is that now you can go and reset the Toolbox and your controls will still be there - after Visual Studio decides it is time :-) which usually happens when switching from html/aspx view do design view.

kick it on DotNetKicks.com

Thursday, January 11, 2007 11:58:42 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, November 09, 2006

The standard procedure when working with ASP.NET Web Projects looks more or less like this:

1) Open/Create a solution in Visual Studio
2) Add/Change some of the pages/code in the solution
3) Press F5 to build and run the project to see the effect of the changes

This procedure has its pros and cons. The main advantage is that we get a debugger support from the IDE, so in case of an exception, we have the possibility to see what and where went wrong. We can also step through the code and see what is being done step by step. Those are only the few of many good things the Visual Studio gives you. 

So what are the drawbacks of this standard procedure? Take for example a page which requires you to login before you can use it. Using the Visual Studio to run the browser you have to login every time you start the debug session. You can somehow work around this problem by creating a persistent cookie (remember me checkbox) so that you will not have to login every time. But what if you have to login using different user name and password? Providing logout button returns you to the original problem. The bigger problem is however with multi-step, wizard-like operations. If you have a 5 steps in your Wizard and something goes wrong on the last step, you have to close the browser to stop debugging (ASP.NET does not support the edit and continue feature with the standard Web Project). Then after making the required changes you have to start the wizard all over again.
Keep in mind that those are only simple examples to illustrate the problems and benefits of the standard approach. They are in no way complete.

Now, We know that there are problems and there are benefits of the "standard way" but there is another way that I'm sure most ASP.NET developers coming from backgrounds such as PHP know about and use a lot. This solution was the only possible way to test and debug your web applications if you had no debugger support from your IDE - like was the case few years ago and I'm not sure if it is still the case. Basically what you do is run your own browser and navigate to the page that Visual Studio would otherwise navigate to using the browser it has started. Now you can browse through the pages and test whatever you want and in case something goes wrong, you can just make the changes in the Visual Studio and recompile. It is possible since the IDE is not in the debugging state while you do this. (The scope of the changes may cause the running application to reload causing you to relogin, but this will not always be the case)

What we don't get with the alternative way of working with our pages is the debugger support, so now if something goes wrong we will get the error page instead of the break in the debugger. Fortunately you can always attach Visual Studio to a running process hosting ASP.NET and debug the application as usual. After you have found the error you can safely stop the debugger and you browse window will not be closed. Also you will not suffer from the startup time of required fro Visual Studio to start the browser and the debugger. This way instead of the edit and continue you can work with a save and refresh style.

I'm not saying that the second approach is better or worse. I'm only pointing out that in some cases there is a faster way to do things, especially when you are getting irritated by the Internet Explorer's address bar always remembering the wrong addresses :-).

kick it on DotNetKicks.com

Thursday, November 09, 2006 8:56:04 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Wednesday, October 04, 2006

Today I have recieved a request for a sample on how to use MyObjectDataSource control. So without delay I have prepared a very simple web project which allows you to see the ease of use of the my control.

ObjectDataSourceExample.zip (19.05 KB)

Sample is divided into 4 pages explaining how to use some of the features of the control. Descrption is added on each page.

Wednesday, October 04, 2006 6:38:47 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 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 [5]  | 
 Tuesday, August 08, 2006

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 [3]  | 

I have created an ASP.NET controls pack that I'm using on a daily basis. The pack includes:

Control Name Description
Button A Button that supports a Confirmation message before submitting a form.
Image An Image that allows you to set the MouseOverImageUrl property.
ImageButton An ImageButton that supports a Confirmation message before submitting a form and a MouseOverImageUrl.
ImageCheckBox A CheckBox that renders itself as an image either checked or unchecked. It also supports MouseOverImageUrl for both states.
MyObjectDataSource An ObjectDataSource that supports build in sorting and filtering of returned objects.
CompareValidator A CompareValidator that supports displaying error messages as an image.
RequiredFieldValidator A RequiredFieldValidator that supports displaying error messages as an image.
PageParameter A parameter that can be used in DataSource controls parameter collections such as SelectParameters. It allows you to get parameters from properties of a page.
TemplateControlParameter A parameter that can be used in DataSource controls parameter collections such as SelectParameters. It allows you to get parameters from properties of a nearest TemplateControl.

I find those control very helpful on a daily basis and hope you will like it also. Note also that some of them I have described earlier but now I provide them as a one download with a full source code. It is available here: Controls.zip (50.7 KB).

Using most of the controls should be obvious. The most complicated one is the MyObjectDataSource. Mostly I have described it in my previous articles about this control. I have added a filtering feature by specifying FilterParameters on the data source control. There are two options: you can either use the internal filter mechanism which will filter values for you or by providing an additional parameter to a select method that is used for selecting objects. This additional parameter should be of type Dictionary<string, object> where the key is the name of the property to filter. Working with internal filter requires almost no code for example using ControlParameter:

<asp:ControlParameter Name="Role.Id" ControlID="Role" PropertyName="SelectedValue" />

Where Name attribute corresponds to a name of the property by which you want to filter and PropertyName corresponds to a property on a control that provides a value to filter by. (I know it my not be very intuitive, but that is what ASP.NET provides and I have been building on top of that). Filtering currently works similar to SQL LIKE command with wildcards before and after the expression.

If you work without internal filter you have the responsibility to filter the collection yourself given the filter parameter to passed to a select method.

kick it on DotNetKicks.com

Tuesday, August 08, 2006 12:06:14 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Monday, August 07, 2006

All of us who have been using any kind of ASP.NET Templated Controls such as FormView, sooner or later come to a problem of extracting value from a field inside a template. For example when you are using a FormView control and want to programatically access a control inside one of the templates. What are the options? You have to resort to some kind of FindControl calls which are way from perfect. I have been thinking about this issue for some time now and I have an idea.

The idea is to change tha way the PageBuildProvider constructs the part of class that represents the ASPX file of your page. (the other one is of course the code behind). So what could be changed? Imagine a situation where you have a page and there is just one FormView on it. The FormView has its templates defined in an ASPX file. What happens now is the ASP.NET framework builds the part of the class given this ASPX file and what we get is a nice intellisense in the code behind telling us that the our class has a field FormView1 of type FormView which of course does not have any knowledge about controls inside the templates. But what if...

But what if instead of the FormView1 being of type FormView, the part of the class constructed from ASPX file provided us with a field FormView1 of type derived from the FormView but with few additional properties which represent controls found inside the templates - in a strongly typed manner.

Now. The benefits of such a solution are obvious mainly compile time type checking.

Is it possible to make ASP.NET 2.0 to provide such a solution? This is a hard question. I have checked the major components that are responsible for the way the classes are constructed now. I haven't gone deep into details but it it looks like some changes inside the PageBuildProvider (or some base classes) would be required. Also a ControlBuilder responsible for building a templated control would have to constuct a whole new class representing our control. I suppose that the major problem lies in constructing such a derived class with all those properties representing inner controls.

So basically I hope MS will/is thinking about making our lives easier and more type safe :-) or maybe some brave developer is willing to try to implement my concept? Either way it would be nice to have such a feature some time in the future.

Some additional considerations include the problem with accessing controls from ItemTemplate of a FormView control when in Edit mode. Another issou would be with controls such as GridView where some of the templates represent a repeating content and not a single data etc...

kick it on DotNetKicks.com

Monday, August 07, 2006 10:11:13 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

ASP.NET 2.0 comes with a mechanism called two way databinding which allows us to declaratively bind a form element to a property of an object in such way that updates are supported. For the readonly display you typically use the Eval method in your aspx page. For the two way mechanism, you use the Bind keyword (or method?).

Using the Bind keyword is really simple in most scenarios that you encounter, especially if you are using the SqlDataSource control. Problems start to come up when you try to use a more object oriented approach and use the ObjectDataSource control.

Now, still in most cases using ObjectDataSource will not cause you any problems when what u bind is a simple property such as a name of a client i.e.: you have a collection of clients that you bind to a GridView and one of the columns displays the name of the client. To do so you use something like Bind("Name"). The problem arises when you need to bind to a subproperty such as in Bind("Address.StreetName"). This won't work unfortunatelly...

Why it is not possible to perform a two way databinding in such a way, there are discussions over the Internet. BTW: Eval("Address.StreetName") works as expected. So what can we do about it? Of course there is a solution for this problem and it has came to me when I was thinking why there is no such a problem when you use the SqlDataSource control.

The reason why there is no such problem when you are working with relational data is that you are creating an SQL query that is a VIEW of the data that you want to display i.e.: it has all the columns you need and there are no "sub-columns". So what we need to do is to translate this to an object world.

So basically what we need to do is create an object that will serv as a view on our objects and bind to this view object. For example given the aforementioned client object with a name and an address we create a ClientView object that encapsulates our client object and exposes the needed properties such as Name or StreetName. Those properties in turn call on the properties of the client object either directly as in Name or to some nested property as in Address.StreetName.

Making a select method used by the DataSourceControl to return the collection of ClientView object should not pose any problem. When using such a technique I would suggest putting the view classes somewhere outside the domain model since the only reason they exist is to allow for the two way databinding to work so there is no reason to pollute the model.

kick it on DotNetKicks.com

Monday, August 07, 2006 10:08:44 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 

Today I have been struggling with a typical table layed out page. It was a MasterPage with few ContentPlaceHolder controls - one for content, one for menu and few for other things. The problem was that the place holders were inside the td elements and some of the elements were made in such a way that they dropped shadow (background-image) and it was not possible from the content page to override this behavior (at least not in a clean way). First I have tried to override the style which made the cell to have an image at the bottom by adding the style element inside one the contents. Unfortunatelly it is not valid html to do so. Then I have thought about adding a ContentPlaceHolder inside the head element. Unfortunatelly Visual Studio does not provide the ContentPlaceHolder control in the intellisense so I thought that it will not wokr... But it did!!!

What is a very good thing to know is that despite the VS not telling you about it, you can put a ContentPlaceHolder inside the head element. You can work with it just like with any other ContentPlaceHolder by providing default content for example. It can also be used as a place for additional page level style elements. One great feature that VS DOES provide is the fact that in the content page, when you edit the head ContentPlaceHolder, you get the intellisense for the head element so you wont see any divs or other body elements there.

After this discovery I have made a search on google to find if anyone had the same problem and I have found the following: artcle.

kick it on DotNetKicks.com

Monday, August 07, 2006 9:59:46 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [3]  | 

I have made some research on how to create a container control - a control which works in a similar way as the Panel control does. There are three key thing you have to do in order to make it work:

  • Add ParseChildren(false) attribute
  • Add PersistChildren(true) attribute
  • Add Designer(typeof(PanelDesigner)) attribute where PanelDesigner is a custom class deriving from ContainerControlDesigner. I haven't tried it, but I suppose that using the ContainerControlDesigner in with Designer attribute would also do.

It's all. You do not have to add any more code. Since, the custom PanelDesigner does not require any code, the question arises - why do we need it? Shouldn't it be some kind of attribute?

A creative usage for such a control could be for example when you need a panel control which has some kind of static content, or maybe images as borders. You get the picture.

Monday, August 07, 2006 9:54:06 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

I have used my PathsBuildProvider a while now and I have came across some issues. I have found two major issues.

The first issue had to do with the fact that from some strange reason the development web server treats root directory "/" in a different way than IIS. So redirecting to /aplicationname/page.aspx has different effect those two servers. I have made a change so that the property is not statically encoded to return a string but rather to use System.Web.VirtualPathUtility.ToAbsolute("~/Default.aspx"). As far as I know it works on both IIS and the development server.

The second issue has to do with the application name being encoded in the code as in Paths.WebTest.Default_aspx. Imagine however that you deploy your application under a different name say WebTest2. It no longer works and strange things happen. To overcome this I have changed the code to allways use the AppRoot as a root directory name.

I have also included the changes proposed by Will Gant. The changes are simple yet brilliant. He proposed that the properties returning file paths to be static. In fact that was what I have first implemented but then I have run to a problem with doing something like Paths.AppRoot.Directory1.Directory2.Default_aspx since if all properties are static than I'm not able to return anything meaningful (an object instance) from such property. Will's solution uses a fact that when you reference a directory as in Paths.AppRoot.Directory1 what you really get is not a property Directory1 of AppRoot object/class, but a namespace qualified Directory1 class name which in turn has static properties.

As usuall, the code is available here PathsBuildProvider.zip (11,13 KB).

Monday, August 07, 2006 9:48:46 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 

After a lot of time spent on working with the Page.ClientScript.GetWebResourceUrl method made it work and it was good. I had my ImageCheckBox control which worked well using this method. The problem occured when I have inherited from the control in another project. It stopped to properly reference the javascript from the resource url. After short investigation I have found the that the problem was caused by the call Page.ClientScript.GetWebResourceUrl(GetType(), ...); The GetType method of course returns a different type when called inside the inherited control and so, the web resource url was incorrect. A quick change to typeof(ImageCheckBox) fixed the issue.

So basically it is worth to take a minute and think when to use the GetType and when to use the typeof.

Monday, August 07, 2006 9:47:51 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

I do not often rename the controls that I do not use in the code behind code, so when I place a Label on a page it most often is named something like Label1. It does not make a big difference when you are not paying for the bandwidth and you only have a few controls on a form. Imagine however that you are working with Master Page and there you are using the defaul ContentPlaceHolder1 as a place for pages to put their contnet. Now it is only 19 characters long yes? But when you look at the generated html, you will see that each control put on a page using such a Master Page has its ID prefixed with the ID of the placeholder. A quick calculation on one of my pages and It appeared that for 100 controls on a page I was wasting 2000 characters only for the id of the placeholder!!! Just renaming the placeholder from the default ContentPlaceHolder1 to something like CPH saves 1700 characters. Such a name change does not cause any major inconvinience on the developer's part since you will rarely reference the placeholder by its ID.

The same mechanism holds true especially for controls such as GridView and UserControls which tend to have a long ID.

Currently I'm renaming all my controls that I put inside a GridView or FormView templates to one letter strings since I'm not using them. I also rename all my controls on pages to a shortest string that I can come up with without loosing the meaning.

kick it on DotNetKicks.com

Monday, August 07, 2006 9:47:00 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 

While working with my validator controls that support displaying images, I have come to a situation where I needed the image to be themable. Easy you think?

Not so easy as it should be. I have added the Themeable(true) attribute to an ImageUrl property, put a control on a page set everything in the skin file, compilled and... ??? No it didn't work. Url points to the same directory as specified in the skin file but is not prefixed with the theme folder name. A quick reflector peek at the Image control and the solution was found. There is a little known UrlProperty attribute that has to be applied to a property which we want to behave as expected when applying urls from skin files.

Monday, August 07, 2006 9:45:06 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

I have been trying to make the Validation controls show an image instead of plain text in case of an error. In doing so I have used Reflector a lot.

My investigation had lead me to some conclusions and even more questions. The main problem here is that for some creepy reason, the BaseValidator inherits directly from a Label control!!! Now I have always been aware of this fact but it was until not long age when it struck me how bad decision it was on Microsoft part. Keeping the parent class in mind it should be obvious that making a Label display as an image was not going to be an easy task.

There are few possible ways in which you can make the validator control show an image instead of text. One of them is providing a img tag as a Text property for the control and it works, but is very unellegant. I thought that it is time to get to know the new feature of ASP.NET 2.0 - the Control Adapters.

After a rather long time it came out that it is not possible to use the control adapters for the validation control since some of the important logic that renders the control is in the Render method of a BaseValidator class and it cannot be easily replaced. I have left the adapter path but having learned a lot nonetheless.

Afer yet more time I have realized that the only real solutions are to either create my own classes implementing the IValidator interface - good there is such a thing or use some third party controls. I had however no spare time for writing my own fully blown controls and choosing the right toolset of third party controls is also time consuming I have decided to take a dirty shortcut.

Below is a listing of all the things I have done in my inherited validator control. Baasicaly I'm changing the TagKey to img, I'm providing a property for users to specify the ImageUrl. The rest is to trick the BaseValidator control to render image instead of a label. The important thing is that the Text property has to be something different than a null, empty or white-space string - otherwise it is possible that ErrorMessage will be rendered inside the img tags which is invalid.


protected override System.Web.UI.HtmlTextWriterTag TagKey
{
get
{
return System.Web.UI.HtmlTextWriterTag.Img;
}
}
public string ImageUrl
{
get {
return (string)(ViewState["ImageUrl"] ?? String.Empty);
}
set { ViewState["ImageUrl"] = value; }
}
protected override void
AddAttributesToRender(System.Web.UI.HtmlTextWriter writer)
{
writer.AddAttribute(
System.Web.UI.HtmlTextWriterAttribute.Src,
ResolveClientUrl(ImageUrl));
if (!string.IsNullOrEmpty(Text))
{
writer.AddAttribute(
System.Web.UI.HtmlTextWriterAttribute.Title, Text);
writer.AddAttribute(
System.Web.UI.HtmlTextWriterAttribute.Alt, Text);
}
base.AddAttributesToRender(writer);
}
protected override void
RenderContents(System.Web.UI.HtmlTextWriter writer)
{
// to prevent rendering
}
[DefaultValue("Error")]
public override string Text
{
get
{
return (string.IsNullOrEmpty(base.Text) ? "Error" : base.Text);
}
set
{
base.Text = value;
}
}

kick it on dotnetkicks.com

Monday, August 07, 2006 9:43:07 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, August 03, 2006

Some time ago I have posted an article about using Build Provider feature of ASP.NET 2.0 to build a strongly typed classes for accessing the files found in the application virtual directory. I myself have been using this provider ever since for every Response.Redirect(). I hope that it serves you as well.

I have found yet two more ways of using the Build Providers to make your applications safer (the second one I will describe in few days). Today I present to you, the ClassPropertiesBuildProvider. This time we get a strongly typed way to access name of the properties of our objects. When this could be usefull? Of course everywhere where we have to specify the name of the properties using a plain string. And where could that be? Mostly in data-binding expressions such as Eval and Bind.

Take for example a sample data-binding scenario where we bind a GridView control to an array of Client objects. Each client has Age, FirstName and LastName:

As you can see we get the full intellsense over available properties. Keep in mind that those properties actually return a string containing the name of the property - exact thing needed to use the Eval or Bind. Notice also that in case some property changes its name, or is deleted, we get an instant compile time error as oposite to the runtime exception you get when you use a not strongly typed Eval("Age").

Using the ClassPropertiesBuildProvider is similiar to the PathsBuildProvider. Just add extension=".cpbp" type="ClassPropertiesBuildProvider.ClassPropertiesBuildProvider" to a web.config file and put one or more file with .cpbp extension in the App_Code directory. In this file the first line declares a namespace under which the classes will be generated ("Classes" in this example). On the following line put the name of the assemblies you would like to have analyzed.

The solution is available as a source and binary here: ClassPropertiesBuildProvider.zip (57,43 KB).

As with PathsBuildProvider, the provided solution is for demonstration purposes and as such you should be aware that it might not always work as expected. If you find some bugs, or wish to provide some improvements, please feel free to do it, and contact me so I too can benefit from it :-)

kick it on dotnetkicks.com

Thursday, August 03, 2006 4:59:21 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

While working on MyDataSourceControl (see my other articles) I have found an interesting thing. It appears that when properties of a control are set to the values provided as attributes in the aspx file, the control is not yet very functional. The most important thing that my be not set is the Parent and other control-tree related properties of the control! It seams however that it is not always so. I may be mistaken, but from my observation it is possible that sometimes the Parent property will be set before the properties defined in the aspx. If somebody can shed some light on this I will be grateful.

Thursday, August 03, 2006 4:53:45 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

When developing stateless applications sooner or later there comes a time, when you need to store some information between requests. In technologies such as PHP and ASP.NET there is a special object to serve this function. It is called the Session object in ASP.NET. Using it is very easy, just use an indexer in a form of a string to set and retrieve some information that you want to persist between requests. Now the main problem with such an approach is the fact that it is hard to control. As an example: suppose that there are two pages using the Session object to store some state and make it accessible to each other. The simplies approach is to just use the Session object on one page to store an object and on the other to retrieve it:

Page1.aspx
Session["SomeKey"] = "some value";

Page2.aspx
object value = Session["SomeKey"];

Suppose further that there are many pages that access the value with "SomeKey" key. Sooner or later (sooner) you will lose a track of where and what is setting and retrieving this value. More over, it is hard to change since it requires you to look through multiple files - a very error prone technique.

Another solution would be to use some kind of public constant variable in place of the "SomeKey". It is better but not perfect.

A more secure solution would be to create a strongly typed class for accessing the Session object by means of properties. This way you only have to change session related stuff in one place and every braking change is detected at the compile time. Additionaly, when working with other developers, they do not have to ask you, what kind of object is available through the Session[“SomeKey”].

As a side note I would strongly encourage you to avoid Session object whenever you can. It is a hell to work with a statefull statless application :-(

kick it on dotnetkicks.com

Thursday, August 03, 2006 4:52:46 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

There comes a time when you have to develop a page which allows its users to go back to the page they came from. Keeping in mind the statlessnes of the web applications, it is hard to tell where our users came from since every page is (or at least should be) working on its own. Suppose that on one of the pages we want to put a kind of “Cancel” button which takes users back. One possible way of doing it would be to use some client-side JavaScript such as history.back(). What if for some reason the use of JavaScript is inacceptable?

We are left with the server-side code. But there is a problem. On the server, there is no way of telling the previous page. We have to create our own solution. There are couple of possibilities here. You can use a Session or Profile object and every time a page is loaded put some information there so we have a way of checking where the user was before. You can even use a Stack object to make it possible to drill down and up as you like. This solution has however an impact on the server resources (memory occupied by the session object). Another solution uses the query url to pass the returnUrl address of page from which the users came. In fact this pattern is used every time you try to access a page which requires authorization and you are redirected to a login page. This way you save some valuable server resources and make your solution a lot more scalable.

kick it on dotnetkicks.com

Thursday, August 03, 2006 4:44:18 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 

Have you ever wondered when is the Select method of the ObjectDataSource called in the page life cycle? It probably depends on your particular page configuration, but on an ordinary page or user control, the select method gets called after the OnPreRender method and before the OnPreRenderComplete. Keep this in mind if you want to perform some custom logic after the whole control tree has been built.

My friend has checkd the SqlDataSource control by handling the Selecting event and the he found out that the same holds true for it also.

Thursday, August 03, 2006 4:43:18 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

I have been using MyObjectDataSource control for some time now with great success. I have however observed one thing that was missing. The missing thing was the possibility to use the container on which the control was placed as the actual TypeName object which provides the methods for Select, Insert, Update and Delete. Oh, of course it was possible before by using the TypeName and providing the name of the type that the page inherits from, but it had two major drawbacks:

  1. It required the page object to be instantiated 2 times: one for handling the request and the second time to provide an object on which the DataSource methods were called. (possible workaround was to use static methods, but then, no page state information was available)
  2. Providing a type name for a page is not so easy. It depends on few factors. By default the type name is the name of the code behind class with _aspx postfix. But it can be anything you choose by using the ClassName attribute of the Page directive in the aspx file.

So I have made some changes to the control and now if the TypeName property is not specified, the methods of the containing object are used. Further more, the same object is used as the one used to serve the request. Of course all the rest of the functionality remains unchanged. The source code and binary file is accessible here: MyObjectDataSource.zip (30,43 KB).

kick it on dotnetkicks.com

Thursday, August 03, 2006 4:38:50 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

There is a little known feature in ASP.NET that is called the "Server-Side Comments". What is cool about this feature is that it works server side.

Using Server-Side comment is similar to using Html comment in all respects but one. ASP.NET does not process any content a block commented in such a way. This may be very usefull if what you want is to temporarily disable some part of the page and that part performs some logic other than rendering itself. Ordinary Html comment will not prevent ASP.NET from including the commented controls in the page life-cycle so your Page_Load methods will fire with Server-Side comments they will not.

Thanks to the this kind of comments you will no longer have to temporarily delete some part of the page just to make it work, because some control was throwing exceptions.

kick it on dotnetkicks.com

Thursday, August 03, 2006 4:33:37 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

I have always wondered how practical if at all is writing the test first. Now, for me the most questionable thing was the fact that working in such a way I do not get any help from the editor. It came to me as a surprise that not only I do not miss the intellisense telling me what parameters I must pass to the method I’m about to call but I get a far more powerful feature instead...

I had already modeled the problem domain in classes. One of those classes was the User class. Now the time came to create a custom MembershipProvider that will integrate smothly with my classes. The classes of course were not created with the Membership feature in mind, so it was obvious that some methods will need to be implemented. I have started coding. At first I have created MyMembershipProvider and inherited it from the MembershipProvider class. Next I have moved to implementing each method. Suppose that I have started with nothing more than an empty User class declaration. The first method to implement on the MyMembershipProvider was the ChangePassword method. I have started typing:

Note that there are no methods to chose from, so I start typing the desired method name:

Once I get to the end Visual Studio detects that there is no such method defined on the User class and offers me an option to generate it (using the smart tag - ALT+SHIFT+F10). Of course I use the feature and what I get in the User class is a static GetUset method with two string parameters named after the variables I have used. The method also returns a user object. It also throws an Exception with message that the method is not implemented (I wonder why not the NotImplementedException). I have implemented the whole MyMembershipProvider in such a way and it went really smothly.

It is not hard to imagine what would happen if the place I first write the GetUser method is in fact a test method and the whole implementation of MembershipProvider is in fact a NUnit TestFixture. We would have a test-first written fragment of code which is what TDD is all about.

I strongly encourage everyone to try this approach. It is not only possible but it also leads to a much cleaner solution with only those methods that you really need and not the ones you think you will probably sometime use.

kick it on dotnetkicks.com

Thursday, August 03, 2006 4:26:16 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

I have blogged about the problems with ObjectDataSource control and proposed two solutions neither of which was perfect. Today I will present a complete working solution. The code and .dll for this project is accessible here:MyObjectDataSource.zip (30,43 KB).

My solution deals with the problem of partially updating an object by providing a way for a developer to provide an instance of a business object on Updating event. Values read from the form are then transferred to this object. This solves the problem with properties not present on the form are reset to default because of the fact that object is constructed by the data source control. It also solves the problem with forcing the developer to provide a default constructor for each business object.

Unfortunately having to hook up to the Updating event would mean that instead of providing a default constructor, the developer would have to code the event handling method. This would not be such a big gain. Fortunately it is not necessary to provide the business object to the Update method by means of Updating event. If an object is not provided, it is retrieved using the Select method for which we already should have an implementation shouldn't we? Indeed we have, because otherwise how would we have displayed the object for editing in the first place? The only problem is that the select method should be able to accept the same number of parameters as was specified for the DataKeyNames property of the control which was bound to the data source control. This should not pose any problems since such a method will exist anyway in most cases.

Using the control is almost identical to using the ObjectDataSource control in that it requires you to specify the Select, Update, insert and Delete methods and a type name of an object providing those methods. Methods may be static or not. I wouldn't recommend using business objects for this. Rather create a separate classes to serve as a service layer for the control. Additionally the control makes a lot better use of DataObjectMethod attribute then ObjectDataSource. If a required Select, Update, Insert or Delete method name is not specified, the control will search for this method using the mentioned attribute. It will also automatically choose the method with required number of parameters. This make it super easy to build an application really fast.

The proposed solution I'm providing has one more feature which everyone should find really useful. This feature is called InternalSort and does just that - it is a generic sorting mechanism which will sort any strongly typed collection using a property specified in the sort expression. (reverse sort is also possible by adding DESC to the sort expression - ASP.NET does it automatically).

Ok, you ask: Where is the catch? One major inconvenience in using the control is that it does not have any support in form of designer. This makes it necessary work with it using the property editor. It also does not interact very well with controls such as FormView - i.e.: FormView does not generate templates given the configured data source control - like it would when used with ObjectDataSource.

If the described solution looks like it would help in developing your applications faster, feel free to use it. I only ask for one thing: a feedback. I would appreciate any kind of feedback: from "you suck" comments through "I would change this and this" to sending me free pizzas or some other stuff :-)

As a final note I have to say that while creating the control I was using the Reflector quite a lot to get to the guts of the original ObjectDataSource control and SqlDataSource. I have also used the sources of CSLA.NET by Rockford Lhotka, where there is an implementation of the DataSource control which works with the business objects of CSLA which is therefore not very generic.

kick it on dotnetkicks.com

Thursday, August 03, 2006 3:59:50 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

I have blogged about Problems with ObjectDataSource control some time ago. That was a problem I was aware of for some time now. It was until recently when I have come across yet another problem. This time it is with how the DataSource controls handle the SelectParameters. I'm mainly working with business objects so I have little experience using the SqlDataSource but from what I have seen it uses the same mechanism for specifying parameters. The problem is that you can only select a fixed number of parameter sources:

It often happens that you need to get a value from some other location such as a property on a page. What to do when such a need arises? Worry not! There is a solution. You will have to create your own class derived from the Parameter class from System.Web.UI.WebControls namespace. You will need to overwrite some of the methods. As an example I present the TemplateContainerParameter which makes it possible to use public properties defined on a page or a user control as a parameter providers.

public class TemplateControlParameter : Parameter
{
protected override object Evaluate(
HttpContext context, Control control)
{
if ((control == null) || (string.Empty.Equals(PropertyName)))
{ return null; }
TemplateControl templateControl = control.TemplateControl;
Type type = templateControl.GetType();
PropertyInfo property = type.GetProperty(PropertyName);
if (property == null)
{ return null; }
return property.GetValue(templateControl, null);
}
protected override Parameter Clone()
{
TemplateControlParameter parameter =
new TemplateControlParameter();
parameter.PropertyName = this.PropertyName;
return parameter;
}
public string PropertyName
{
get { return (string)ViewState["PropertyName"] ?? string.Empty; }
set
{
if (PropertyName != value)
{
ViewState["PropertyName"] = value;
base.OnParameterChanged();
}
}
}
}

The interesting part here is using the TemplateControl property which will return the reference to a nearest template control containing our parameter which in most cases will be either page or a user control. You can also create a parameter which always uses page properties:

protected override object Evaluate(
HttpContext context, Control control)
{
if ((context == null) || (string.Empty.Equals(PropertyName)))
{ return null; }
IHttpHandler handler = context.Handler;
Type type = handler.GetType();
PropertyInfo property = type.GetProperty(PropertyName);
if (property == null)
{ return null; }
return property.GetValue(handler, null);
}

Here the interesting part is using the Handler property of the context object which in most cases will return the reference to a page object but hidden behind the IHttpHandler interface. It does not mather though since we are getting the property value using Reflection.

The bad news is that you will not be able to use those custom parameters in the designer :-(. The 6 parameter sources shown on the picture above are hard-coded in the .NET Framework library (to my best knowledge). You have to resort to the html editor - as in many more cases, more than it should be necessary :-(.

kick it on dotnetkicks.com

Thursday, August 03, 2006 3:43:56 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

ASP.NET 2.0 comes bundled with a control called ObjectDataSource. At first it looks like it is a perfect solution for all OOP lovers like me. The problem is that in practice it is completly unusable.

There are several problems with the control, the greatest of which are the fact that all objects that are to be updated by the control are required to have a default, parameterless constructor since the Update method takes as a sole parameter the object of a specified type created by none other than the ObjectDataSource control.
(another method is to provide an update method that takes simple parameters representing updated object's properties such as name, age etc. but this solution is even worse since it requires separate methods for every combination of parameters, and defeats OOP feature - the inheritance - altogether).
Now where exactly is the problem? You may think hell I can go with having a default constructor on every object since I will probably need it anyway to support the [Serializable] attribute. But wait! There is one more problem with the control. It creates our business object and sets its the properties!!! Now what is wrong with that you ask? Once the business object is created ALL its fields are set to initial values such as null/1/1.0/false. Next, each property that was bound using the two way databinding mechanism (Bind) is set to a new value taken from the html form. This is of course ok. But what happens to the properties that were not bound using Bind? AHA! Now's the catch. They are not updated with any value and so we end up having a business object with only some of its properties set.

A more realistic example: given a business object User with properties such as Id, FirstName, LastName, Age, Login, Password and a form on which we use an ObjectDataSource control and a FormView control to edit just the Login and Password. Of course the FormView allows us to specify the DataKeyNames so the Id property will be preserved - we will need it to update the right record in the database. The form is first displayed and both textboxes are populated with user's Login and Password. User edits the data and decides to save them. On PostBack the magic happens and the ObjectDataSource creates a brand new User object, sets it Login and Password property with the new values from the form. Such an object is then passed to an Update method expecting a User object. But what to do with such an object? We cannot save it to the database since there is no way to determine if a given property's value is the default value or a value just set by someone and we cannot just save all the new values because that would mean loosing the data that was not edited.
In most cases we cannot even compare the property value with the default value for that property or the value from the database since given an Age=0 we cannot tell if it results from a user's setting or the fact that it was not set at all.

Now. There are multiple workarounds for this problem. One mentioned earlier is to use a separate Update method for each combination of parameters.
The other is a hack. It is possible to fool the ObjectDataSource so that it thinks it uses the parametrized Update method. It is necessary in order to get the Keys and Values from the form. If the Update method is used, there is no way of accessing those values. Next step is to intercept the Updating event. There you will have access to a collection of Keys and Values read from the form (accessible through the event args). You can than get the destination object from the database or from some other location, and copy the new values to its properties using Reflection. Once you have copied the new values to the business object you have a stiutation where the object is properly set: properties present on a form are updated, the other ones are set to the original values and not the default ones. There is just one problem. What to do with such an object and what about the parametrized method? We still need them yes? No! After copying the new values to a business object we have to clear the ObjectDataSourceMethodEventArgs's InputParameters collection and add to it just one parameter - our business object. The good news is that it is only after the Updating event when the propert Update method is selected to be called. The method is selected based on the InputParameters and since there is only one, the Update method expecting our business object will be used :-).

Example code:
void DataSourceControl_Updating(object sender, ObjectDataSourceMethodEventArgs e)
{
IOrderedDictionary inputParameters = e.InputParameters;
// Get the business object
object element = GetElement();
// Copy the values from the form to an object - the hard part
CopyValues(element, inputParameters);
// Clear the parameters list and add a single object to it
e.InputParameters.Clear();
e.InputParameters.Add("element", element);
}

To fool the ObjectDataSource control we have to delete DataObjectTypeName attribute but do it from the html view and forget about using the designer for edditing the control from there after.

Of course the above mentioned methods are not something I would recommend, but for a starter this is the only way I'm aware of you can use the ObjectDataSource. The other way is to write your own ObjectDataSource. This is exactly what I have done and will provide a complete solution in a few days.

Thursday, August 03, 2006 3:12:18 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [5]  | 

I have posted an article in which I describe the PathsBuildProvider that reflects the local file system of a web application as a strongly typed class hierarchy. The most obvious benefit that the provider brings is that once you start to use it, you can say good bye to a 404 error resulting from Response.Redirect to a nonexisting page. It is ensured that the error will occure at compile time sine once there is no file, there is also no property on a class to use as a redirect target :-).

Thursday, August 03, 2006 2:57:36 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Some time ago I have found some articles about a feature of ASP.NET called the Build Providers. I especially liked the one about generating classes representing tables from the database. More on that one on Fritz Onion's blog.
Since then I have found numerous ways of using build providers to make my life easier. Today I have built a library that will greatly simplify keeping all Response.Redirect's up to date.



So without further ado I present the PathsBuildProvider.
Using it is as simple as placing a single file with ".pbp" extenstion in the "App_Code" directory and adding a build provider under the compilation section of of the "web.config" file and:


type="PathsBuildProvider.PathsBuildProvider" extension=".pbp"


The .pbp file should contain one word which will be used as a namespace for the generated types. If the file is empty this namespace will default to "Paths".
From now on you can type your namespace name and when you hit "." the name of the application should appear as the only choice. The instance of this class provides a way to access the names of all files located in the application folder in a strongly typed way i.e.: each file is represented by a property such as "Default_aspx". Such a property returns an absolute virtual path to a file so that it can be used in places sucha as Response.Redirect, or Server.MapPath.
Directories are also accessible by means of the properties prefixed with "_". Each directory provides access to its files and sub directories.


You can see an example of how it looks here:

 

 

I have put the code for the soulution here: PathsBuildProvider.zip (11,13 KB).

Keep in mind that the code is for demonstrational purposes only and as so it is not a production quality :-). Feel free to use it as you wish though. Any feedback is always welcome.

kick it on dotnetkicks.com and/or digg it and/or vote on it on dzone

Thursday, August 03, 2006 2:54:12 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  |