Monday, February 12, 2007

Today while working with ASP.NET I have received a "Internet Explorer cannot display the webpage" error when I tried to get to one of the pages. Other pages worked well. My first thought was to use a debugger of course and so I did only to be presented with a following message:

---------------------------
Microsoft Visual Studio
---------------------------
Unable to start debugging on the web server. Could not start ASP.NET or ATL Server debugging.

Verify that ASP.NET or ATL Server is correctly installed on the server.
---------------------------
OK Help
---------------------------

Strange...
I haven't changed anything in my computer's software configuration for a while now. Why would debugging stop to work when it worked well just few minutes ago?
It had to be somehow connected with that one page I thought so to get this solved I needed a working debugger. First I have killed the w3wp.exe process - didn't help. Next I have restarted a website in IIS - didn't help. Finally I went and restarted the World Wide Web Publishing Service and it did the trick. I had a working debugger so I could work on the main problem.
As it came out, I have made a simple mistake and caused an infinite recursion which caused a StacOverflowException to be thrown. After I have found the problem and corrected it my problem with a debugger came back! Aha! So if there is a StackOverflowException, something gets broken in the IIS!
Few tests confirmed it. I have observed that if a StackOverflowException is thrown while navigating to a page (without debugger attached) - nothing happens. You can do it "safely". If however, you are debugging and StacOverflowException is thrown inside your debugger, it usually takes only one such exception to kill IIS.
How important is this problem? It depends of course, but imagine what would happen if you have debugged a server running a couple of sites and all went down for no apparent reason while you have debugged your code. Fortunately usually it is not possible to run a remote debugger on a shared hosting environment :-)

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

Today I have noticed the existance of an attribute inside System.Web.UI namespace, that made me curious. The attribute was: NonVisualControlAttribute. It was the first time I have seen it (or I don't remember it).

What does this attribute do? The name suggests that it maybe used by some visual tools. The MSDN documentation is not very useful (as usual) providing only information I have already figured out just by looking at the class name: "Defines the attribute that indicates whether a control is treated as a visual or non-visual control during design time" (MSDN). 

So what does this attribute do? I have searched the Internet for a while and found nothing useful, other than what I already knew. Then I have found that Visual Studio 2005 allows you to toggle whether to display Non Visual Controls using View menu. (you have to be in design mode to see this option). When you select not to display Non Visual Controls, they disappear from the design view like it would be expected. Is it useful? I don't know I have never needed such a feature and fortunately, by default, everything is visible.

Being curious, I have checked which controls have the NonVisualControl attribute applied and I have found that there are only 5 in the BCL:

  • DataSourceControl
  • HierarchicalDataSourceControl
  • ProxyWebPartManager
  • WebPartManager
  • HiddenField

When you look at the controls above, the important thing to notice is that "Non Visual" does not mean that the control does not render any html markup. As you can see, the HiddenField is also a NonVisualControl but it renders an input tag. WebPartManager on the other hand renders some JavaScript code.

Finally I have found a post on the very attribute written by Nikhil Kothari where he says the following: "Hopefully, it will be used to do more in the future, so start using it now, where it makes sense."

kick it on DotNetKicks.com

Wednesday, February 07, 2007 10:47:24 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

While working with Visual Studio 2005 the other day I have noticed that my Keyboard Repeat delay has increased. It had happened to me a couple of times before. Always when I was working with Visual Studio so that is why I put the blame on it. Usually I haven't done anything to fix the problem, because it was not very annoying, and usually I could work with it until the end of day. After a restart, everything goes back to normal.

Today I had this problem again, but there were still few hours until the next restart. I had one idea that I wanted to try to see if it can fix the problem. The idea was to increase the Keyboard Repeat delay using Control Panel-Keyboard options. So I did. First I have increased the delay, applied the new settings and right after that I have decreased it to its normal level - the minimum. Voila, every thing worked like a charm. Even Visual Studio!

I wonder if any of you also has this strange problem?

Wednesday, February 07, 2007 10:33:33 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 Tuesday, February 06, 2007

Last time I have posted my observations on the Remember Password feature of Microsoft SQL Server Management Studio. Today it got even worse! Not only MSSMS forgets my password on a random basis, It prevents me from logging in with a correct password! Yeah I have written about it last time, but this time I have entered the right password - 100% sure of that, and despite dozens of connect attempts it always said that login or password is incorrect! So I have retyped the exact same password and voila, after second connect attempt it worked.

Now. I know that there is SQL Server 2005 service pack comming out soon, but does anyone know if the login window will be fixed? Come on! Its only a UI with few imputs! How hard can it be?

Tuesday, February 06, 2007 11:29:32 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 
 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 [1]  | 
 Wednesday, January 31, 2007

During my investigation of how and what of AutoGenerateColumns in GridView in my recent articles, I had a need to check if a type is a Nullable type. I have used reflector to search for a siutable method, but I haven't found one. What I have found though was a strange class: System.Internal. It is internal so it is not accessible outside its assembly, but nevertheless I find it worth mentioning because of its contents.

The class has 3 methods that make me think:

  • CommonlyUsedGenericInstantiations_HACK()
  • NullableHelper_HACK<T>()
  • SZArrayHelper_HACK<T>()

Just by looking at the names I can tell that there is something about them, that is not your usual BCL code :-)

When I have looked inside the first one of those methods I have found a lot of code that only instanties Generic type objects such as List<T> where T is bool, int, Guid etc. The second method on the other hand calls Compare<T> and Equals<T>.

Why is that? In my opinion, all the operations there are perfoemed to improve performance of some code. By doing the operations in a batch, once, at some point in time, we do not risk the JIT compiler compiling every generic class and every generic method on demand later. If this really helps or is useful? I don't know, but MS has done it and I usually do not believe in "random code". Maybe there are some performance considerations in some scenarios that require the HACK approach? I haven't been able to find a place in the BCL that uses the System.Internal class.

kick it on DotNetKicks.com

Wednesday, January 31, 2007 2:37:13 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 

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]  | 
 Wednesday, January 24, 2007

Today I have found a funny example of how to ensure the checkbox is not visible:

<input id="chkIsDirty" type="checkbox" readonly style="DISPLAY: none;
VISIBILITY: hidden; BACKGROUND-COLOR: transparent" size="0" runat="server"
name="chkIsDirty">

I have emphasized the important elements. I wonder if it is also hidden by the style sheets and maybe in the code via the runat="server" attribute :-)

Wednesday, January 24, 2007 3:23:10 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [3]  | 
 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 [0]  |