IndyALT.NET Site is live!


IndyALT.NET is now live!

Right now it’s being hosted in somebody’s house (thx to Paul Hacker, MSMVP, for sharing his servers temporarily!) We’re excited about our first two events! Next month we’re having Mike Griffin come in for some training on the EntitySpaces OR Mapper. In July we are planning on having Todd Anglin come in and show us some good stuff with some of Telerik’s products. And who knows what else we’re going to do!

Interesting and busy times to come!

-Shane



Automatic Generation of API Documentation for .NET 2.0 Code


I was recently given the task to generate some API documentation for all of the code on a project I was working on (11 different projects, 3 different solutions) so I began looking into what was available. I remember using NDoc with old 1.1 projects, but that project was apparently abandanded. Microsoft has an October 2007 CTP release for a replacement called Sandcastle. It’s a suite of files that provide the core functionality of generating HTML and CHM files for documentation in an MSDN-like style. Apparently, this is what Microsoft uses internally to generate their MSDN documentation.

Unfortunately, Sandcastle comes with no GUI to use it but fortunately, there are several free GUIs written out there to do it for you. To find out more about it, I thought this site was most helpful.

-Shane



VS2005 Deployment Projects install new version with old version’s custom action assemblies


I’m working on a project where we use Deployment Projects to deploy our public application. We’re still in beta phase so we don’t have a huge number of releases under our belt yet but so far things have been going pretty well (well, at least since we’ve gotten past the initial hurdles in getting our first installer out). Well, something new has jumped up and surprised us. And honestly, now that I understand it, I’m shocked that we’ve not seen it in any of our last 5ish releases.

So here’s the context: We had a prior version of our app installed and we wanted to upgrade from that version to the newest version. We have the installer uninstall the old version (for this part hopefully by now you know that it’s good and important for all assemblies in the installer to be properly versioned and at or above 1.0). This is done by the freebie stuff and the Uninstall events that get fired within our Installer Class/custom action to manage a few things, including our databases. Next the new version gets installed (again by the freebie stuff and custom actions). The last thing our custom action class does is upgrades our databases from the older verson to the newer version. This is how we’ve done things for the past 5ish versions and everything has worked just fine and dandy as long as we’re on the ball with versioning our assemblies correctly.

Well, this version I updated all of our installer files just as I had done with the previous versions and when I went to test it, I was surprised. For some reason the install seemed to work fine EXCEPT for our custom actions. To make a long story short, what was happening was that our custom actions from our previous version were getting executed when the installer was installing the newer version!! So obviously since our databases are maintained by these custom actions, the problems were pretty obvious from the beginning.

I ultimately found this article online which points to this KB article of Microsoft’s (EDIT: this is the VS2005 version of the bug, I previously linked the VS2003 version of the bug) and it turns out that this is a bug in Visual Studio 2005 that was posted in August of 2004. The short version of the problem is with the assembly name for our custom action. When Windows Installer loads CustomAction v3 for the uninstall and attempts to load CustomAction v4 for the new install, it unreliably does not load v4 because it sees it already has CustomAction loaded but forgets to care about what version it is. So then when the new version of the app fires the events for our DLL, they get handled by the old code and not by the new code.

There are two things to be aware of with this scenario to fix it. The first is an end-user work-around in case you need such a thing for an installation that you might have already made public. If the end-user runs your installer and this happens, running the installer again and selecting “Repair” will then run the correct version of the DLLs. Now this may or may not help you, depending on your scenario. Luckily for us, this is an acceptable work-around without trashing any data because of our architecture around updating our client databases with each release. Now the second thing to be aware of is a more permanent fix. If you change the Assembly name for your custom action to be unique with each deployment, this will allow you to prevent this from happening again. So instead of my custom action’s assembly name being “Company.Project.Installer.CustomAction” it is now “Company.Project.Installer.CustomAction_v1.0.0.3″ and of course I change this with each release.

Good luck and I hope you find this problem and solution before wasting hours of time like I did!



Debugging Visual Studio 2005 ASP.NET apps on Vista Home Premium


If you have an ASP.NET app hosted by IIS7 on any Vista Home edition (though I’ve only used Home Premium), it fails because Vista Home Premium lacks Windows Authentication. Fortunately, Microsoft is aware of this and has issued a fix. Unfortunately, it’s not part of Windows Updates so you’ll have to go get it yourself.

You can find KB937523 here describing the situation: http://support.microsoft.com/default.aspx?scid=kb;EN-US;937523

The fix can be found here: http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=7250



.NET 2.0 Simultaneous Web Service Calls give “The request was aborted: The request was canceled.” error


We’ve been having web requests just randomly fail with an error message of “The request was aborted: The request was canceled.” Simple testing would never produce this result yet real-world use and stress testing would indeed cause this problem. If you Google it and you’ll find many other people with this exact same problem. But finding the actual reason for the problem is a bit more difficult. Luckily somebody (birch9397) opened a ticket with Microsoft and shared it, which hit the nail dead-on at the Microsoft Forums. Here is a snippet that contains the beef of the source of the problem:

It turns out that when you start to make spin up your second set of threads to call the remote web service your ASP.NET application is waiting for a response from the web service but instead the web server resets the connection. Within the dump that I collected we see that there is an exception with the text of “The underlying connection was closed: A connection that was expected to be kept alive was closed by the server”. It appears that the code logic in .NET 2.0 is that when this occurs we will try to resend the web request, however because of the previous exception the m_Aborted property of the HttpWebRequest object is set to true and so we end up getting the Request Canceled exception that you are seeing.

For our next troubleshooting steps I’d like for you to disable Http KeepAlives for the HttpWebRequest object in your .NET 2.0 application. This will force the client to establish another TCP session with the BEA Web server before sending out another web service requests.

In order to set the KeepAlive property of the HttpWebRequest object to false you will need to override the GetWebRequest method within your client application. Please see Resolution D in the following article to see how to do this in your ASPX client page

915599 You receive one or more error messages when you try to make an HTTP request in an application that is built on the .NET Framework 1.1 Service Pack 1

http://support.microsoft.com/default.aspx?scid=kb;EN-US;915599

Luckily, a user there named Antzone gives a simple code snippet showing you how you can resolve this issue for yourself. If you create a wrapper class around your base WebRequest class, you can override the GetWebRequest(Uri) method and set the HttpWebRequest.KeepAlive propert to false in just a couple lines of code. Then everywhere you instantiate your webrequest, simply instantiate this new web request instead.

Not bad and makes many errors go away! :)

-Jax



Losing connections due to ADO.NET bug using Transactions


Environment: ASP.NET 2.0/C#/SQL Server 2005 (SP1 on live servers and SP2 on some development and test servers)

So we’ve been developing an application for many months and finally went live with it. Once going live, seemingly randomly we started getting the following problem:

Fill: SelectCommand.Connection property has not been initialized.
Exception Details: System.InvalidOperationException: Fill: SelectCommand.Connection property has not been initialized.

Once we got this, we remembered seeing it somewhat unpredictably during development:

<backflash>
We were using the MyGenerations OR Mapper for our data tier. This is an open source product so we were compiling it in release mode on our own then just pointing to the DLL. Because it was open source, one of us added the MyGenerations project to our solution to debug the problem, but doing so made the problem go away. We ended up adopting this as a workaround to this problem so we could move on (mistake #1).

Just before deploying our application to the live servers, we had a conversion application that was written to convert data from the legacy system to the new system. Everything worked fine until we tried doing the true conversion – we had this same problem. Somebody stumbled upon a workaround by simply running the conversion utility in debug mode and this worked. Because all systems were down and this conversion tool was a 1-run program before it got thrown away, this was an acceptable solution. However, nobody looked further into the problem (mistake #2).
</backflash>

So now back to the present day. Once going live, it seemed every couple days we’d get this problem. Once this problem occurred, ALL connections (it seemed) were hosed and the entire site was down until we did an IISReset. Because it happened so infrequently and we had no clue how to reproduce it, we just monitored the situation with this defect (while working on many other defects). Over a period of a couple weeks, this problem grew and grew until it was happening 10 times a day (again, we didn’t know how to reproduce it but we were logging the hell out of things from every angle we could think of).

Oh, and one more thing – our database is being hit by 3 independent web sites/servers and they were only going down 1-at-a-time so it was most likely not any issue with the database server itself.

Now the obvious first guess at the problem was that we weren’t closing our connections and the connection pool was running out of them or perhaps we had hanging transactions that were causing problems, or something along those lines. We code reviewed the MyGenerations code up and down, left and right to no avail. Then we started reviewing tons of our code, again, no luck. However, one thing we did learn was that simply doing nothing other than compiling the solution in debug mode made the problem go away!

We finally opened a ticket with Microsoft. After a couple weeks of working with them and one of our guys stumbling upon this post, we finally came to the source of the problem – a bug in .NET 2.0′s ADO.NET. Before I show you the fix, read this snippet from an email from Microsoft after we fixed it that explains the problem at a high level:

Based on your information, I did locate a bug on this. The development team does not have any plans right now for a hot fix, but they are looking at fixing this in the future as the forum post indicates. The issue only occurs when you use the transaction as the sole (or last) reference to the connection. Then there is a brief window when the transaction only has a weak reference to the connection and if a Garbage Collection occurs before it is converted to a strong reference, then it will collect the connection object. The reason it doesn’t show the problem in the debug build is that variables are not freed as early as they are when an application is compiled for Release mode, and so we delay enough the window is a non issue. The workaround is fairly simple once you understand the nature of the problem and that is to keep an external reference to the connection that is outside the transaction object.

So the fix was just as he said it was, keep an external reference to the connection that is outside the transaction object. So in our case, with the help of the MyGenerations developers, we modified the MyGenerations code to do this and our problem is gone, at last! So expect an update to their software very soon to work around this .NET bug. And if you hit this problem with your own code, now you know how to fix it. :)

-Jax



Access ASP.NET Validators from JavaScript


I needed to access clientside validators from JavaScript in order to determine if the page was valid or not.

Turns out MSDN tells you how if you dig deep enough. :)

You have two options:

  1. Access a global flag that essentially loops through all validators
  2. Check each validator, one at a time

#1 is the easy way, just use the Page_IsValid flag to determine this.

#2 isn’t so bad if you know all of your validators. If you do, you can simply access the validator.isvalid flag.

Lastly, it is sometimes useful to be able to force validation from JavaScript on a page before performing an action (such as clicking a submit button). In this case, you can simply call the Page_ClientValidate() function and that’s all it takes!

-Jax



ASP.NET 2.0 – SqlDataSource and GUID / UNIQUEIDENTIFIER fields


Today I ran into a pretty ugly bug in ASP.NET 2.0.50727 (i.e. .NET 2.0 RTM). Imagine you’re using the freebie .NET 2.0 Membership stuff and you would like to list all Roles that the currently-logged-in user is associated with and you’d like to use a GridView to do so. So imagine you create a stored procedure with the query in it and pointing the SqlDataSource to this stored procedure and you’d like to pass that user’s GUID to the SP to display this list. Here would be a simple SP to do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE PROCEDURE MyProc @UserID UNIQUEIDENTIFIER AS BEGIN
 
SELECT
	RoleName
FROM
	vw_aspnet_UsersInRoles UserRoles
INNER JOIN
	vw_aspnet_Roles Roles
ON
	UserRoles.RoleId=Roles.RoleId
WHERE
	UserRoles.UserId=@UserID
END

Sounds simple enough, right? So we would have our ASPX page setup with the following code (assuming the GUID is in a “LoggedInUserID” session variable):

1
2
3
4
5
6
7
8
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1">
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:MyConnString%>"
 SelectCommand="MyProc" SelectCommandType="StoredProcedure">
 <selectparameters>
  <asp:SessionParameter Name="UserID" SessionField="LoggedInUserID" Type="Object" />
 </selectparameters>
</asp:SqlDataSource>

That is the code that the Visual Studio 2005 IDE generates for you when you go through the point-and-click interface. The problem with this is that you get the following SQL Error:

Implicit conversion from data type sql_variant to uniqueidentifier is not allowed. Use the CONVERT function to run this query.

Obviously something is wrong with the datatype .NET is sending to SQL Server. Note that the IDE told us to use “Object” type which, indeed, makes sense that SQL Server interprets that as sql_variant. So what type should we specify in our ASPX file? Our options, according to Intellisense, are: Boolean, Byte, Char, DateTime, DBNull, Decimal, Double, Empty, Int16, Int32, Int64, Object, SByte, Single, String, UInt16, UInt32, and UInt64. The only things in that list that aren’t obvious that we can rule out without thought or trial are Char, Empty, Object, and String. So let’s look at our remaining options…

Char
This is talking about a C# char data type, not a SQL char field which means only 1 character can be stored in this data type. This won’t work.

Empty
For some reason, this actually works! But only in this case. I’ll revisit this case later.

Object
We saw above that this case throws an error.

String
This case throws a similar error but instead of converting from sql_variant, it’s erroring when implicitly converting from nvarchar.

So the answer we have so far is to use the Empty type for this parameter, right? It appears so but when I tried this in a more complex example, it definitely didn’t work. Change the Type=String and modifying the SP such that it accepted a varchar as that parameter and later explicitly converting it to UNIQUEIDENTIFIER, this made the more complex example work.

So the first thing I asked myself was, “What is this ‘Empty’ data type anyways?” Well, that’s something I didn’t know so I began to look it up. Unfortunately, I couldn’t find much of anything stating what this was. As such, I’m currently stuck on why this is happening this way.


Jaxidian Update is proudly powered by WordPress and themed by Mukkamu