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 [0]  | 
 Friday, May 11, 2007

For a long time now I have been working with only one monitor. For a developer it poses some difficulties like lots of overlapping windows. Without even really knowing how it is really like I have always been an advocate of a dual monitor setup. Now when I have a laptop and an external LCD I can only say that I was right, but at the same time wrong!

Two monitors give you much more space on which you can put your windows. For instance you can put a help window on one monitor and the code on the other. If you work with ASP.NET you can have a browser running on one of the monitors while you edit the code on the other and take advantage of Edit and Reload feature. Possibilities are almost countless. Almost...

The one thing that I was wrong about is the fact that my primary development tool: Visual Studio 2005 does not support dual monitor setup! Can you imagine? The only support available is that you can move SOME of the windows on to the second monitor. The windows you can move include Solution Explorer, Watch, Immediate and all the other dockable windows. Good as it is, I think it is only a side effect of those windows being draggable. The problem is that Visual Studio was never intended to be used on more than one monitor and that is why you cannot move the most important windows to the second monitor. What are the most important windows? For me it is the code window and the design window (ASP.NET).

At first I thought that I might be missing something. Some switch in the preferences. Unfortunately it is simply impossible according to the following sources:
http://blogs.msdn.com/saraford/archive/2005/07/20/441126.aspx
http://blogs.msdn.com/saraford/archive/2004/05/18/134295.aspx

That's a pity. I cannot wait for the next version of Visual Studio in hope that they will add the support for more than one monitor.

Friday, May 11, 2007 2:10:31 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 

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 20, 2007

From time to time I need to find out if the code that is currently executing runs in a Hosted Environment (like ASP.NET application) or not (like Windows Forms application). Mostly those kind of knowledge might be needed in reusable assemblies which deal with file access. For ASP.NET application you almost always need to call Server.MapPath method (or one of the equivalents). For Windows Forms Application you either do nothing or call something like Application.StartupPath.

There are many ways to tell if code is hosted or not. Usually I see code similar to the following:

if (HttpContext.Current == null)

This code however requires a reference to a System.Web.dll which may not be something you take lightly :-). So I thought: lets see how They do it - that is how Microsoft does it.

It appears that they use a System.Web.Hosting.HostingEnvironment.IsHosted property to make this check inside System.Web.dll. Still this is a System.Web.dll that you have to reference to make the check. I have been unable to find any alternative that does not require this reference, but hey! I'm a web developer mainly and I have nothing against referencing System.Web.dll :-)

Tuesday, March 20, 2007 11:11:26 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, March 19, 2007

I have always believed that each collection is by definition IEnumerable. That belief held true until today...

First let me define my loose definition of what a collection is. A collection is a set of objects. In .NET Framework I have noticed a special pattern for naming collection classes - they usually end with a Collection word. Examples include dozens of collection classes in System.CodeDom namespace, AttributeCollection or even ControlCollection. I'm so used to this kind of naming convention that when I see it I automatically know that I can do a foreach loop over it.

There is however at least one exception from this rule and that is a System.Web.UI.CssStyleCollection class. It is a class that derives directly from System.Object and it does not implement any interface which means no IEnumerable!!! When I looked at the public properties, they suggest that it should really be a collection. It has an indexer, it has a collection of keys and values. It even has a Count property not to mention all the usual methods for manipulating collection-like objects.

Strange, but true :-)

 

Monday, March 19, 2007 4:56:11 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 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 [0]  | 

There are a lot of articles on how you can debug you JavaScript code using Visual Studio 2005. There are basically two cases:

  1. Debugging ASP.NET pages inside the Visual Studio's solution.
  2. Debugging other pages - not included in the solution.

In the second case, all you have to do is attach to a process of a running Internet Explorer using Debug->Attach to Process... menu option, in the first case, all you need is to run the solution in debug mode.

The rest of the scenario is the same for both cases. Visual Studio allows you to open any script document currently loaded into the Internet Explorer process you are currently attached to. This is done via the Script Explorer window which you can turn on using Debug->Windows->Script Explorer menu option or by using the Ctrl + Alt + N keyboard shortcut. The window should look more or less like this:

The problem is that more often than not, debugging JavaScript in Visual Studio simply does not work! I have spent countless hours trying to find the solution or even the cause of this problem, but without success. There are many "solutions" on out there but none of them really solves the problem. Most of them simply don't work! Probably Microsoft fails to acknowledge this as a problem since it has been around for few years now - judging by the news group posts dates.

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

There is a bug in Visual Studio 2005 (but I think I have also seen it in Visual Studio 2003) that causes multiple break points to be set in case you have few files with the same name opened using Script Explorer window. (if you are fortunate enough to have it working).

Steps to reproduce the problem are simple. Just ran a simple page with a Textbox and a Button control and some kind of Validation control. This will ensure that the presence of two "WebResource.axd" JavaScript includes: one for with Validation code and the other one - the standard ASP.NET one. Try to set a breakpoint in the first line of any of the script files included. Use Script Explorer window to get the files. Notice that the breakpoint appears in both files. Also sometimes the focus is moved to one of the other files. Imagine having a couple of scripts included in such a way and all those unneeded breakpoints!

As mentioned above, I have noticed this behavior also in Visual Studio 2003, but I have not tracked it down. I'm almost sure however that there was also the same type of problem also with normal files included in the solution. (yet again, I can't remember for sure).

Fortunately removing breakpoints works correctly so you can remove unnecessary breakpoints once they are created.

As a side note. While writing this article my Script Explorer windows stopped working and this also means that script debugging inside Visual Studio also does not currently work, so I'm unable to provide any more details. I hope though that Microsoft will correct this problem sometime in the future.

Friday, March 09, 2007 5:45:48 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 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 [0]  | 
 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]  |