Friday, June 15, 2007

Today I was working with System.Uri class a bit and I must say that it is very useful. Just imagine checking if a given URL is absolute or getting the host name from URL or even getting the query part. All of this is implemented in this one class by means of properties like IsAbsoluteUri, Host, Query etc. There is however one problem...

While playing with System.Uri I encountered a situation where while trying to create an Uri object I got the following exception:

System.UriFormatException was unhandled
  Message="Invalid URI: The format of the URI could not be determined."
  Source="System"
  StackTrace:
       at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
       at System.Uri..ctor(String uriString)

Of course there is nothing wrong with it. Not every string represents an Uri. So, remembering about the pattern found in classes such as Boolean or Int32 I looked for a TryParse method. As it came out, System.Uri doesn't have a TryParse method but there is TryCreate method instead. After changing the code to use TryCreate method and running the application it came out that I still have a problem somewhere.

At first I thought that the problem was the TryCreate method! In all cases where the normal constructor failed for me, the TryCreate method not only returned true, but also constructed a System.Uri object!

The following code demonstrates the issue:

string url = "asdasda";
Uri uri;
if (!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out uri))
{
}
else
{
    uri = new Uri(url);
}

The above code should run smoothly, but it will throw the mentioned System.UriFormatException. The reason for this is that when using the constructor, we should also use the overload that allows us to pass the UriKind as an argument!

Friday, June 15, 2007 8:11:15 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 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 [4]  | 

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 [4]  | 
 Monday, May 28, 2007

From time to time I have to create a form that is used both for display and input of data (or in other words for viewing or adding/editing). As an example, imagine a form for entering customer data. The form will include fields such as Name, Address etc. There are few possible solutions to this problem.

First and most easy to implement is to create a single form, put required input controls on it: one TextBox for Name and one for Address. When constructing the page on the server, we have to check if the form is used  in View mode in which case we have to set the controls' ReadOnly property to true. Otherwise we can leave it as false. ASP.NET controls mostly support this kind of mechanism. The problem is that a ReadOnly TextBox is still rendered as HTML input control. You can try to hide the fact by using CSS styles, but underneath it is still an input control for a form that does not require one.

Another solution I have seen used a lot is to create a separate page used only to display the date and another page for editing/adding data. In this case, the page used to display data uses controls such as Label control so no input field is generated. The other page works as can be expected. The problem with this solution is that now we have two pages and some of the logic/layout/whatever is duplicated.

ASP.NET architecture to the rescue! Since ASP.NET is designed in such a way that it makes heavy use of controls, we can take advantage of the fact and introduce a special kind of TextBox control that is intelligent in a way it renders itself.

The way to achieve this goal is simple. Create a new Class, make it inherit from the TextBox control and override few methods:

public class TextBox : System.Web.UI.WebControls.TextBox
{
    [DefaultValue(false)]
    public bool RenderReadOnlyAsText
    {
        get { return (bool)(ViewState["RenderReadOnlyAsText"] ?? false); }
        set { ViewState["RenderReadOnlyAsText"] = value; }
    }
    protected override void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer)
    {
        if ((!RenderReadOnlyAsText) || (!ReadOnly))
        {
            base.AddAttributesToRender(writer);
        }
    }
    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
        if ((RenderReadOnlyAsText) && (ReadOnly))
        {
            System.Web.UI.WebControls.WebControl span = 
            new System.Web.UI.WebControls.WebControl(System.Web.UI.HtmlTextWriterTag.Span); span.RenderBeginTag(writer); writer.Write(Text.Replace(Environment.NewLine, "<br />")); span.RenderEndTag(writer); } else { base.Render(writer); } } }

Notice the RenderReadOnlyAsText property which is false by default making the new control behave just like a normal TextBox. Next we need to override the Render method. I have used span control to replace the normal input control, but feel free to experiment. The thing to remember is to replace the NewLine characters with HTML line breaks (probably some CSS style would also do). Additionally I have overridden the AddAttributesToRender method so that it does not add any attribute to the control in case it is rendered as a plain text (or span in my case).

Using this control on a page is simple. Just set the RenderReadOnlyAsText to true and set ReadOnly property to true when necessary.

kick it on DotNetKicks.com

Monday, May 28, 2007 4:34:05 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 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]  |