Archive for annoying

brief list of things that make working in C# frustrating

Problem: .NET framework classes don’t use interfaces enough

Specific example: DataSource / DataBind()are separately defined on Repeater and GridView, (and Control, and many, many others), and my abstract base class doesn’t care which option an implementor chooses, it just wants to bind the data however the base control wants it.

Possible Solutions:

  • Define interface IDataBinding, class MyRepeater : Repeater, IDataBinding, class MyGridView : GridView, IDataBinding, etc.
  • Define interface IDataBinding, upgrade to C# 3, use extension methods to add IDataBinding nope, extension methods can’t do this
  • Copy/paste identical code from my base class into concrete classes
  • Use reflection to set DataSource and call DataBind(), completely sidestepping the C# type system

Problem: .NET framework classes not designed for extension: “cannot override inherited member 'System.Collections.Generic.Dictionary<X, Y>.Add(X, Y)' because it is not marked virtual, abstract, or override

Specific Example: Extending System.Collections.Generic.Dictionary to do some permit a list of values for one key, so adding the first item is stored as a single value, but adding a second value to the same key stores both values in a list. Error message is: “cannot override inherited member 'System.Collections.Generic.Dictionary<X, Y>.Add(X, Y)' because it is not marked virtual, abstract, or override

Possible Solutions:

  • Define wrapper classes that encapsulates the framework class and implements all the base interfaces, with the vast majority of the code being straight delegation to the framework class:
    class MyDict : IDictionary, [other interfaces...] {
    private Dictionary<X,Y> dict = new Dictionary<X,Y>;
    public bool Contains(X key){ return dict.Contains(key);}
    [... other simple wrappers...]
    }
  • Find a less appropriate framework class that is designed for extension, duplicate behavior of the proper framework class manually, eg: add run-time type checks for Hashtable.Add(object, object) in place of the letting the compiler handle the types as in Dictionary<X,Y>.Add(X, Y)
  • Extend Dictionary<X,Y>, define a method AddList(X,Y), and avoid using IDictionary in the rest of my code
  • Upgrade the C# 3, use extension to add function AddList to IDictionary, be sure to include those extensions on every consumer of IDictionary

Problem: .NET framwork classes not designed for extension: members declared private/ internal / protected internal

Specific Example: Storing additional data in ViewState on 2 different controls that have different base classes. One is a user control, another extends RadioButtonList to provide different UI for the same data

Possible solutions:

  • Upgrade to C# 3, use extension methods to add functions nope, extension methods can only see public members, ViewState is protected
  • Use reflection to set ViewState
  • Copy/paste code into each control
  • Define interface IPublicViewstate, class MyRadioButtonList : RadioButtonList, IPublicViewState, class MyUserControl : UserControl, IPublicViewState, etc

As Nathan said, I’m stuck between a rock and IHardPlace.

Comments (2)

SQL Server 2005 doesn’t like bitwise comparison of large numbers

An update trigger using COLUMNS_UPDATED() was failing, and I figured out the problem:

Some simple SQL:

SELECT CAST(0×0200 as bigint), 0×0200 | 0
SELECT CAST(0×02000 as bigint), 0×02000 | 0
SELECT CAST(0×020000 as bigint), 0×020000 | 0
SELECT CAST(0×0200000 as bigint), 0×0200000 | 0
SELECT CAST(0×02000000 as bigint), 0×02000000 | 0
SELECT CAST(0×020000000 as bigint), 0×020000000 | 0
SELECT CAST(0×0200000000 as bigint), 0×0200000000 | 0
I had “IF COLUMNS_UPDATED() | 0 > 0″ in my trigger, and on large values of COLUMNS_UPDATED(), bitwise ORing with zero equals zero.  Of course, “IF COLUMNS_UPDATED() | 0 > 0″ is a retarded way to say “IF COLUMNS_UPDATED() > 0″, but whatever codepath that large number triggers wigs out there to.  Try these out:

SELECT 1 WHERE 0×0200000000 > 0
SELECT 1 WHERE CAST(0×0200000000 as bigint) > 0

So, to fix my trigger, I have “IF CAST(COLUMNS_UPDATED() as bigint) > 0″, which still seems a little retarded, but at least my trigger works.

Comments

Quicken 2007 fails

I use quicken to manage my finances, and find it overall does an excellent job, but every now and then it does something outrageous:

quicken-fails.png

Seriously?   You still can’t handle that?  I guess that means its time to take another stab at gnucash.

Comments

“manual or distributed transaction mode”, ruby, rails, mssql, ado

Spent too much damn time debugging the database layer in rails again today. This was the error:

OLE error code:80004005 in Microsoft OLE DB Provider for SQL Server
Cannot create new connection because in manual or distributed transaction mode.

This was getting thrown after an insert, and the problem was very non-obvious.  I found one potential solution on Occasionally Useful Software’s post about Ruby and SQL Server, but that seemed a little heavy-handed.

Somewhere in the bowels of ActiveRecord, dbi.rb, ADO.rb, and the SQLNCLI driver, something expected one result-set per SQL command. My insert was firing a database trigger, and so the ruby stack saw two result-sets, one saying “1 row affected” for the original insert, one saying “0 rows affected” for the trigger. I’m still a little confused, as I thought those “rows affected” messages were separate from proper result-sets (the results from a SELECT, for example), but apparently those little buggers count enough.

Adding a “SET NOCOUNT ON” to the top of the trigger fixed it.

Comments (1)

Debugging Shibboleth and “error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate” errors

Mucking about with Shibboleth again, and ran into some errors on the SP, specifically:

2007-07-10 19:49:42 DEBUG SAML.libcurl [79] sessionGet: SSL read: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate, errno 0

This is the “catch-all” error message for Shibboleth OpenSSL Errors. After much research and testing, it was a problem with the IdP, their server was rejecting my client certificate.

How it should work (I think)

  1. User requests protected content on the SP
  2. SP redirects to the IdP for authentication
  3. IdP authenticates user, sends an SSL (with client certificae) SOAP request to the SP with some info, and then redirects the user back
  4. SP validates SOAP request by comparing client certifacte with a white-list in the shibboleth metadata
  5. SP sends an SSL (with client certificate) SOAP request to IdP to get more information about the user (in my case, a username so I can identify them in my database)
  6. IdP validates SSL cert of SP with a white-list in their shibboleth metadata, responds with whatever information was requested
  7. SP uses that information to serve or deny access to the user from step 1

SSL cert problems can happen at steps 4 and 6. You can test these somewhat by using openssl on the command line. Openssl has about a brazillion options, but the one useful here is s_client(1).

Be sure the SP recognizes the IdP’s certs

First up, check that the SP has the IdP’s certs in order:

openssl s_client -connect HOST:443 -showcerts

That will give you back the certificate chain:

Certificate chain
0 s: SUBJECT FOR THE IDP
i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)05/CN=VeriSign Class 3 Secure Server CA
—–BEGIN CERTIFICATE—–
ASCII JUMBLE
—–END CERTIFICATE—–
1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)05/CN=VeriSign Class 3 Secure Server CA
i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
—–BEGIN CERTIFICATE—–
ASCII JUMBLE
—–END CERTIFICATE—–

Server certificate
subject=SUBJECT FOR THE IDP
issuer=/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)05/CN=VeriSign Class 3 Secure Server CA

some other stuff…

The issuing certificate (in the example, cert 1) should be in your shibboleth metadata. All you need is the top-most issuer, and shibboleth will look down the certificat chain until it finds a certificate it trusts, and all will be well.

If that doesn’t solve it, then we see if the IdP has the SP cert straight.

Be sure the IdP recognizes the SP’s certs

This is harder to debug from the SP’s side, but you can try make an SSL connection using the SP cert and key:

openssl s_client -connect HOST:443 -showcerts -cert SP.crt -key SP.key

If that connects, then you know the server isn’t rejecting you outright, but it’s possible that Apache config is rejecting you elsewhere. The best way to check is to just ask your IdP if your config is still in their shibboleth white-list.

If that doesn’t solve it, check the apache config.

Be sure everyone’s apache config is OK

The possible failure here is that the certificate is being rejected before making it to shibboleth. You don’t want to tell your whole server to accept any client certificate, you want to just pass those through to shibboleth and let shibboleth decide. You’ll want to have SSLVerifyClient optional_no_ca in your Apache location blocks for shibboleth URLs.

Conclusion

Certificates are a good idea, but a pain in the ass. The shibboleth-users mailing list is a good source of information, and you can get prompt replies from there. And next time I have this problem, I’ll know where to look for debugging tips.

Comments

EventHandlerList, key equality, and auto-boxing in C#

I was recently implementing some custom events, and found a couple of good (if old) articles describing how to do this efficiently using EventHandlerList:

Those articles go into why it's nicer to deal with one EventHandlerList instead of many seperate EventHandlers, so read those for more information. For the lazy, here's some code showing how you're supposed to use these things:

C#:
  1. public class MyClass {
  2.     private EventHandlerList Events = new EventHandlerList();
  3.  
  4.     public event EventHandler MyEvent {
  5.         add { Events.AddHandler("MyEvent", value); }
  6.         remove { Events.RemoveHandler("MyEvent", value); }
  7.     }
  8.  
  9.     public event EventHandler MyOtherEvent {
  10.         add { Events.AddHandler("MyOtherEvent", value); }
  11.         remove { Events.RemoveHandler("MyOtherEvent", value); }
  12.     }
  13.  
  14.     protected void OnMyEvent(object sender, EventArgs e) {
  15.         EventHandler handler = (EventHandler) Events["MyEvent"];
  16.         if (handler != null) {
  17.             handler(sender, e);
  18.         }
  19.     }
  20.  
  21.     protected void OnMyOtherEvent(object sender, EventArgs e) {
  22.         EventHandler handler = (EventHandler) Events["MyOtherEvent"];
  23.         if (handler != null) {
  24.             handler(sender, e);
  25.         }
  26.     }
  27. }

Pretty straightforward stuff. When you add an event handler to the list, you associate it with a key, and then when its time to trigger the events, you look for any handlers under the same key. The other day I was putting together something similar, and ran into some unexpected behavior with the keys. I had started by refactoring the magic strings into an enum:

C#:
  1. protected enum MyEvents {
  2.         MyEvent,
  3.         MyOtherEvent
  4.     }

and replaced all the strings with members of that enum. I figured this would work just fine, but the change caused my unit test to fail. Upon debugging, the EventHandlerList was always returning null in my On*Event calls. After some more testing, the pattern became apparent: value types don't work as keys. This was somewhat unexpected, as I've used enums like this in Hashtables all over the place before. After doing a little Reflectoring, the actual search for the key comes down to traversing a linked list with a simple equality test, something like this:

C#:
  1. while (head != null)
  2.     {
  3.         if (head.key == key)
  4.         {
  5.             return head;
  6.         }
  7.         head = head.next;
  8.     }

The culprit ends up being C#'s auto-boxing. The key is stored as an object, so my value types are being boxed on the way in, and therefore == is comparing object identity, not the object values. If EventHandlerList used head.key.Equals(key), everything would have worked how I expected. The solution to rid myself of magic strings now becomes using static objects as my keys, so the object identities will match:

C#:
  1. private static readonly object MyEventKey = new object();
  2. private static readonly object MyOtherEventKey = new object();

That pattern reminds me a lot of enums in Java before it got a enum keyword, which came on the heels of C#'s nice solution to the enumerated type problem. It'd be nice if I could use enums for their intended purpose, but cases like this make me a bit wary. Where else in the .NET framework am I going to find object identity equality where I expect to find object value equality? Is there some rational explanation for this, or is this just a bug?

Comments

Codeplex wastes six months reinventing wheels

I saw an announcement today that CodePlex, Microsoft's version of Sourceforge, has released a source control client. From the release:

A common theme we've heard from our users is the desire to be able to work offline (in the "edit-merge-commit" style) when working on their CodePlex projects. Six months ago, we started working to write such a client that would integrate with our existing TFS server infrastructure, and today we've released our first beta of the client.

The CodePlex Client is a command line client for Windows, and requires .NET 2.0.

This infuriates me. This cool thing they spent six months (six!) writing is called Subversion, and it had a 1.0.0 release three years ago. Subversion had its first beta in late 2003, so the Codeplex folks are waaay behind the state of the art on this one.

As a whole, I think the state of software is abysmal. The only way to make it better is to stop writing new code. New code is always full of bugs, and its an expensive path to get from blank screen to stable program. We need to treat programming more like math, we need to build on our results. Development tools is a special market, as our needs are all very similar, and when we need a tool, we have the skills to make it.

The Codeplex staff stated they needed to write their own client in order to integrate with the TFS server infrastructure. According to an msdn article (Get All Your Devs In A Row With Visual Studio 2005 Team System), TFS seems to be a complicated tool to help manage your developers. Reading the description, TFS seems to be an issue tracker, unit tester, continuous integration, source control system, and visual studio plugin. So, basically a combination of Trac, NUnit, CruiseControl.NET, Subversion, and a visual studio plugin. Why not just write the visual studio plugin, and hook into the tools people are already using? All those tools have rich plugin-architectures that would probably support any sensible addition you'd want to make.

This problem is ingrained at Microsoft, which feels the need to brand everything, but it is in no way limited to them. A search on Sourceforge for "issue tracker" gives 585 results. Sifting through those to pick a winner is difficult.

It's more fun to write new code than read old code, but this fun wears off. After a certain initial momentum creating your new tool, you will inevitably come to a realization "this is going to take me for-fucking-ever". Unless your itch is particularly strong, you'll probably quit, and the world will be cursed with a 586th buggy issue tracker. By writing a plugin, you can ride the new-code high usually from start to finish, since its a much smaller task.

Reading code seems more difficult, but I think that's largely perception. Its just another puzzle to solve. Once you get over the idea that reading code is more difficult, it's really not that bad. For most mature projects, it's probably easier for you to read through someone else's mound of debugged code than it is to write and debug your own mud-ball.

I think we need find and evolve extensible tools, and stop trying to write them over again. We can get the custom behavior we all need by writing and debugging plugins, which are going to be orders of magnitude faster and cheaper than writing the whole system from scratch. I see this happening already, with communities forming around different tools to share plugins.

Next time you need a development tool, don't open a new code file. Do us all a favor, open up a browser, and just re-use previous results.

Comments (41)

Server Application Unavailable, no event log, .NET 2

A perplexing error while setting up my new system:

Server Application Unavailable

The web application you are attempting to access on this web server is currently unavailable.

Please hit the "Refresh" button in your web browser to retry your request.

Administrator Note: An error message detailing the cause of this specific request failure can be found in the system event log of the web server. Please review this log entry to discover what caused this error to occur.

The web leads me far astray. I did not have anything in the event log.

The solution? Give MACHINE/ASPNET permission to my project. I found this a LOT faster by switching to .NET 1.1 in IIS, and that gave a much more useful error message. I guess "Server Application Unavailable" is .NET 2's way of crapping its pants.

Comments (1)

Tightly coupled systems are unmaintainable

Yet another example of why I believe this:

Microsoft told me to update to IE7, so I did. To test something in IE6, I'm installing MS Virtual PC 2004 (provided free by MS), and running an image of Windows XP that has IE6 (also provided free by MS). I am following this article from the IEBlog: IE6 and IE7 Running on a Single Machine.

I downloaded both files, and now all I have to do is debug the installation of both. MS Virtual PC thinks I don't have a checkbox checked, but my network settings disagree. Windows doesn't think the compressed OS image I downloaded from Microsoft is a valid exe file.

I appreciate that Microsoft is trying to help me out, but making IE7 a separate program from IE6 would be much more helpful.

I guess I'll try rebooting.

Comments (4)

Ease Parsing enums in C# using generics

Once constant annoyance I've had with C# has been parsing a string into an enum.

Original C#:

MyEnum e = (MyEnum) Enum.Parse(typeof(MyEnum), "myvalue");

Using generics let you write a function to help:

public static T ParseEnum<T>(string name) {
  return (T)Enum.Parse(typeof(T), name);
}

So then you can simply* say:

MyEnum e = ParseEnum<MyEnum>("myvalue");

A little nicer, but still annoying.
*: simply for C#

Comments (3)