A collection of learnings and opinions.

Thursday, August 2, 2007

DropDownList with a blank item on top

The DropDownList (DDL) is a nice little databindable control in ASP.Net. The easiest way to use it is to databind it to some value from your database and let the user select.

The problem with straight on databinding is that the first item in the DDL will be the first item in the databound collection (naturally), thus making choosing that item "a little too easy" and "a little too hard". When the user wants to select the top item you might be in for problems, as that selection won't fire off a SelectedIndexChanged -event, which is what you'd normally listen for.

There are ways around this - I've seen several suggestions. None of these are even starters in my opinion:
  • Don't handle changes in the DDL, read from it on some other event (typically a button)
    • This makes it very hard to create responsive UIs, as your user will always have to keep clicking buttons
  • Set whatever you want to happen on changes in the DDL as if the first choice was already chosen (pre-choose for the user)
    • Badness - especially in a stateless media like the web - your user may never correct your initial (possibly wrong) assumption
  • Add an empty record in the databound object (typically your database)
    • Perhaps the worst idea I've seen. The database should not contain filler like this. It's a bit better if you're working with some transient object - but still it's a hack. We don't like hacks.
The way to fix this problem is really not very hard. What you want is an empty item on the top of the list that the user will not expect to work, with a known value you can check for in your SelectedIndexChanged handler.

To do this add a ListItem to the DDL in the page/control's definition with your sentinel value and an empty string as the Text property. Normally this item would disappear on databinding, but wait: set the AppendDataBoundItems property on the DDL to True, and your empty initial value will survive!

Two things to beware: Make sure you check for your sentinel value in the handler, and remember to clear all but the initial item of the DDL's ItemListCollection if you're databinding that control again later (unless you want to keep appending).

Here's your illustrative code:
A standard DDL:

<asp:DropDownList id="ddBasic" runat="server" autopostback="True">
<!-- Selecting the top item will not fire an event (it will be pre-selected) -->
</asp:DropDownList>


A DDL with the empty top-item:

<asp:DropDownList id="ddWithEmptyTop" runat="server" autopostback="True" appenddatabounditems="True">
<asp:ListItem value="-1" text=""> </asp:ListItem>
</asp:DropDownList>


Technorati Tags: , , ,

Thursday, July 26, 2007

Glotton - word glutton


I've launched a new small open-source application, Glotton. Get it at http://code.google.com/p/glotton/

It's my summer holiday, and I've been playing some word-games (in particular Scrabble and BookWorm). I'm not particularly good at these, but I find them fun.

What I can do, however, is to get a computer to help me. So I did - I created Glotton.

It is free, open-source and available for whatever use anyone may put it to. The easiest way to use it is to download the pre-packaged zip, extract this and run the jar-file.

Send me a note if you like it or find any bugs.


Powered by ScribeFire.

Wednesday, June 27, 2007

Error ... error ... whence cometh thou?

I'm working on a page that will allow our users to view a table in a database in ASP.Net. To do this I am writing a UserControl where I am connecting to the database through a SqlDataSource, and I bind a GridView on the UserControl to this datasource. If you are unfamiliar with databinding this simply means that I hook the presenting controller (the GridView) up to an object that can provide it with data. This automagically populates the presenter with the data from the source. But, as with all automagical things can, and do, go horribly wrong.

Small digression: I'm from the Java plains, but I've recently set up shop in the .Net woods where I mostly hang around in the soppy marshes of ASP, the glossy banks of MSSQL-RS and more recently the crags of ADO. Being quite new in these parts I get to do a lot of really stupid things, and I'm building an appreciation of each land's pros and cons. One of my gripes with the marshes of ASP is the incessant focus on doing things declaratively as the first-choice. Sure, it's great if what you want is static, but I don't want static content!

Why this rant? Declarativity just bit me in the rump, like a particularly nasty ass.

So, I was binding my GridView to the SQLDataSource declaratively, like a good ASP-ape. Everything was working as expected until I started testing the page with non-standard inputs. The datasource is setup with the data it needs to connect to the database, and an initial select statement to get at the data you want. If any of this is incorrect the entire page explodes in a messy way. Red goo all over the walls.

My test-case was simply setting up the datasource with an incorrect login. This caused an SQL-exception when the SQLDataSource tried to perform the initial Select (as one would expect). Now, .Net does not have checked exceptions (expect a post on this later), so being from the Java-land I am always a bit surprised and worried to see exceptions being thrown willy-nilly run-time.

Well, this exception I should be able to deal with. It is a real problem, but the application should be able to handle such problems gracefully. I just had to find some place to catch this exception, and handle it.

There are several places you can handle an error in ASP.Net:
  • global.asax (where you can handle application-level errors), overriding one of the following methods
    • Gobal_Error
    • Application_Error
  • Page_Error (where you can handle errors on a page-level)
In addition to this you can define a page to send the user to in case of an error, so the plebs don't have to see the ugly innards of your app. All of these solutions are good, but not for my use-case where I actually wanted to handle the exception, should it occur. These solutions let you do things like log and redirect on errors, but offer little in the way of actually handling the problem.

Yes, on a page I could have used the Page_Error, the problem is that I am building a UserControl, which is part of a page, but not the page itself. And, a UserControl has no onError event to catch, and on Error method to override. In effect the UserControl blew up, killing all bystanding controls and page-elements.

Digging in to where the error originated I saw that it was spawned when the controls on the page where coming to life, in the preRender -stage of the lifecycle. This tells me that I must place some code to handle this before that stage of the lifecycle to avoid this error. In the purely declarative mannar I would declare a handler for some SqlDataSource error event, but that component does not have one. So I am relegated to provoking the error myself, and handling it correctly.

This is not really all that hard, once you've gotten to this level (the realisation that I had to do it this way took much longer than the coding of the fix). What you're forced to do is to not bind the GridView to the SQLDataSource declaratively. Read that again. To handle the error you're forced to step out of the declarative world and do the binding yourself. Now, this isn't hard, but it suddenly seems as if the declarative way of doing things is second-rate and sunshine-days-only. I can live with that, but what I really don't like is how every example focuses on declarative implementation, when it's the less powerful and (to me) less natural way of doing things. Sigh.

Oh, well, on to the fix. Just remove the DataSourceID="someDataSource" element from your GridView decalaration, and add something like this to you Page.Load handler:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
theGridView.DataSource = someDataSource
Try
GridView1.DataBind()
btnSave.Visible = True
lblError.Visible = False
Catch exc As SqlException
lblError.Visible = True
btnSave.Visible = False
lblError.Text = "Could not load table: " & exc.Message
End Try
End Sub

This will let the UserControl come up, even if the datasource experienced an error. Much better, but I'm left feeling it's dumb that I have to do it this way.



Technorati Tags: , , , , , ,

Tuesday, June 26, 2007

Let's Talk About It...

"Let's talk about it..." that's the name of the latest version of Jade, that was released yesterday! That's right, a new version of everyone's favourite FIPA-compliant Java-based multi-agent framework has a new release. And this is just, what, a month or two since the first book about the framework was released (Developing Multi-Agent Systems with JADE).



Exciting times!



So, what's new in this release? Any breaking changes? Let's have a look at the press-release (I haven't had time to try it out yet. I'll do that at my first opportunity and post my impressions).



  • A whole new communication mechanism: Publish/Subscribe!
    • A whole new mechanism where agents can simply register a topic they are interested in, and every message that is broadcast with that topic will be sent to them. This sounds like a good idea to me, uncoupling the broadcaster and subscribers. It is only applicable to general broadcasts, though, and I wonder how they implement "closed" lists.

    • Sounds like they are implemented by making a proxy-AID representing the topic, to ensure compatibility. I wonder if this is a good thing, is breaking the agent-AID binding really something you want to do?

  • A "completely restructured version of the Web Service Integration Gateway"
    • Web app (can be deployed to app servers, like Apache Tomcat)!
    • Web-services are derived from the actions in the ontologies registered to the Directory Facilitator.
    • WSDL document generated for each agent service exposed (how did they do it before?)
    • I haven't used the WSID earlier, so I can't really add any thoughts to this, check out the guide here.

  • Improved detection of main container using UDP Multicast packets

    • Excellent, this makes it easier to set up multi-platform environments!
  • A reflector, finally allowing us to use the Java Collections Framework when working with ontologies
    • Excellent stuff, now just port the entire thing to Java 1.5 to give us generics!

All in all some exciting stuff! Let's hope this one doesn't break anything, eh? I've not touched it yet, and so far on the mailing-lists there's one user who's had problems with the multicasting on his machine, but it looks like a he found a workaround (detect-main option set to false).



Let the bugsearch ensue :-)



If you met God on your commute

Here's a nice little story...



Talking to God...





Monday, June 25, 2007

Which tables do I have available?

Sometimes when you're connecting to a database you'd like to know what tables are available. I'm no DBA, so it took me a while to find out how to do that.



In this case I've just gotten the connection stuff from the user, and I run this code when the user presses a "Connect" button to connect to the database the user has specified and populate a drop-down box with the user-tables in that database. The real meat here is the selectTables string in there, which gets the user-tables from the sysobjects table. Once I get this I bind the drop-down box (ddTableSelect) to these to show all the tables.

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnConnect.Click

Dim builder As New System.Data.SqlClient.SqlConnectionStringBuilder



builder.DataSource = txtDatasource.Text

builder.InitialCatalog = txtInitialCatalog.Text

builder.UserID = txtUserID.Text

builder.Password = txtPassword.Text



Dim selectTables As String = "SELECT sysobjects.name, sysobjects.id " _

& "FROM sysobjects " _

& "WHERE sysobjects.type = 'U'"



Dim source As SqlDataSource = New SqlDataSource(builder.ConnectionString, selectTables)



ddTableSelect.DataSource = source

ddTableSelect.DataTextField = "name"

Try

ddTableSelect.DataBind()

connectedState()

Catch ex As Exception

lblError.Text = "Could not connect: " & ex.Message

errorState()

End Try

End Sub

To be perfectly clear, as VB can be a real pain on the eyes (and SQL is soooo much better, right!?) this is the SQL that gets the tables:



SELECT sysobjects.name, sysobjects.id 

FROM sysobjects

WHERE sysobjects.type = 'U'





Yes, I know, catching all exceptions in the end there is bad, but this is me feeling my way, ok?



There's a bug in the compiler

Or so they say.



I was making a new page-control today for my app. Using VS this can be done by adding a new controller to the page through menus, or you can just do what I do. I copy an old one, and paste it in, changing the Class names and removing most of the code. This bypasses all the tedious setup, and all the bits that have to be there for the framework I'm working on are already there. Goodness.



Happily I build, expecting no errors, but I get a nasty message. "Custom_Report is ambiguous in the namespace 'ASP'". Not good. Custom_Report was the name of the control I copied, so I go back and double-check that I changed the class-name. Yes, yes I did.



That's strange. Well, a quick search online told me that this might be a result of a known bug in the compiler. The fix was easy, you have to compile your app in non-batch -mode. How do you do this, I hear you asking. Simple: enter the compilation section of your web.config, and set batch="false", as so:

<compilation debug="true" batch="false">

...

</compilation>


This has been your small-problem, small-fix.

Sunday, March 11, 2007

Don't Store That Password (Client)

Passwords, passwords, passwords. They're all around us, and they're a pain to remember. How do we cope? There are hundreds, possibly thousands of places where I use passwords. I have trouble remembering one password, those numbers would be ludicrous to even try. How do you cope? You make up a strategy, or you get tooled up.

Traditionally we say there’s three main ways of asserting an identity. Something you are, something you know and something you have. Identification consists of proving one or more of these to a given level of confidence. A low level of security could include simply asking someone who they are. If you want a higher degree of certainty you could ask for more than one element of identification.

The most common way of doing this is by asking for two of the three elements above, who you are and something you know (username and password). When you want higher degrees of security you can add the third element (something you have, like a key) or you can go deeper into each of the elements. Going deeper into who you are is the direction of biometrics. Delving into something you know would include asking questions you’d know but none others would, and not asking the same question every time. Gaining security on the “have” element would include making very sure the item really does belong to the person who’s trying to identify himself and making equally sure that thing really is that thing. One-time pads and secure transfers are key here.

This all seems nice, and it is. You know what else it is? It’s a hassle. So far most services contend themselves with a two-pronged check (username/password), so you need to give that to get access. This is fine for one or two services, but we’re all consumers of hundreds or thousands of services. To add to this you really should keep different passwords for each service, to ensure your security. If you use the same password for every service and one of your providers are hacked (or *gasp* are bad-guys and sell or use your password) all your information is compromised. So we make up passwords.

To protect ourselves from brute-force hacks we make up complicated passwords with at least 8 characters and combinations of upper-case (A-Z), lower-case (a-z) and numbers (0-9). The really paranoid among us throw in a couple of non-obvious ones too (β, æ, °, etc). And you have to remember all of this. It’s all a bit hairy.

We need some way to solve this problem. Luckily there are solutions. What you need is a strategy to keep track of your passwords. There are three obvious strategies (well, more, but this isn’t a book, it’s just a post).

1. Make up a (hopefully strong) password and stick with it for every service.
This is a bad idea in general, but it’ll do if you don’t care about the information you put into the services. This means your information is wide-open to any hacker after they’ve somehow gotten hold of your password.

2. Make up a few (hopefully strong) passwords and use different ones for different services.
This is what most people do. You have one password for your work-things, one for throwaway-accounts you don’t care about, one for your personal stuff, etc. Although this is a step up from number 1 it’s still not what I’d call security. Two things to think of here are:
a. Are you sure your other passwords aren’t stored somewhere you can get to from one of the identities? If you store a list of passwords on one account any hacker who’s gotten into that has access to all your other information.
b. Are you sure you won’t try all possibilities if you can’t gain access on one service? If a hacker has control over some service you use and changes the password he could probably get a few good passwords out of you when you try all the possibilities. I know I would try every option before giving up.

3. Make up some personal rule for your passwords. This is a good way of coping with the problem as long as you keep this rule secret. Say your rule is “The first three letters are from the beginning of my pet’s name, after that every even character spells out my post-code backwards, every odd character spells out the name of the service. Every other letter is upper-case.” This would make my youtube –account’s password “eRo1E6b1U5tUoY”. Kind of cool, and quite hard to break as long as you don’t tell anyone what your rule is.

So we have some inkling on how we could do this, but it’s still a hassle (well, number one isn’t really). So we’d like some tools to help us. Number one doesn’t really need a tool, perhaps a paper-note if you’re a goldfish. Number two could also be covered by a piece of paper, but with tools we can improve on this. This is where personal password-keepers live. You make up a set of passwords and keep them somewhere safe (like in a database). Safe as in – won’t disappear, and hopefully safe as in won’t get to others. However if your password-database is compromised you’ll effectively have shot your guard in the rear. You’re wide open. And, let’s be fair here, you won’t use all those random passwords anyway. It’ll be too much of a pain and you’ll go back to your old scheme of one or a few passwords.

The third option though is still fascinating. If it’s an easy rule you can use quickly you won’t need a tool. However, with a tool you can make a really complex rule that nobody would ever guess! The world would be your oyster! A one-way-function would be ideal for just this purpose! Hashing-functions are popular for this purpose.

Hashing for dummies:
For our purposes hashing-functions are a black box you put some number into, and some other number comes out. Every time you put the same number in the result is the same, and crucially, there’s no easy way to go the other way! If someone had your result (the hash) and the hashing-function (the black box) they still have no easier way of finding the number you put into the black-box than trying every possible number. (This is all slightly false, but it’ll do for now).

So, what you do is get yourself a hash-function and enter the name of the service into that function. This way the hasher can make you a service-password that’s unique for that service, has no apparent connection to you and will be generated every time you put the name of the service into the function. Oh, you say, but everybody else using the same hashing-function would get the same password! And, you’re right, I’m proud of you. You’ve obviously been paying attention. What you do is you “salt” the hash. Salting the hash means you don’t just enter the name of the service but also enter something else. This “something else” would be your master-password.

Let’s assume you’re able to remember one password and what you called the service – this will always give you the password for the service. As long as nobody else has the same password and name for the service they’d not have the same service-password. Even if they did any hacker with control of the service wouldn’t know what the password-name-combination was, he’d only see the service-password.

This is great, the problem is solved. Well, the problem was already solved with strategy 3 back up there, but people are too lazy to think of strategies. Now, how can lazy people get to use this marvelous technology? We have to give people hash-functions! Luckily these are available. Popular ones are MD4, MD5 and SHA-1 (I know, they’re broken but they’ll do for our purposes). You can try them out at http://pajhome.org.uk/crypt/md5/

If you use Firefox (and I think you should) you can install a bookmarklet called SuperGenPass This makes the entire operation automated, and it fills in the generated password based on the name of the server you’re trying to connect to and your master-password. It’s so easy you’d never think it was safe, but it really is!

This has been a short essay about how the client can get some security from hacked or malicious services. As a developer I see the problem from the other side as well. I’ll delve into that next…

Been Sick

I've been out sick for a while, sorry. That's why there's been no new posts for a few days. Just thought I'd tell all my millions of readers.

The good news is that I'm well again, and I've got a few posts coming out soon.

For now, take a look at the interesting things I've put on the sidebar. Not my content, but all of that is stuff I found interesting and worth a little time.

Monday, March 5, 2007

Tell Me When Something Happens

Events are a staple of object-oriented design. They are a way decoupling objects and that is almost always a good thing. A short synopsis of the idea:

You have some object (Foo) and you want to be able to know when something happens to Foo. Say Foo is a button and you want to know when it's been pressed in order to do something. You could just code Foo to do the thing you wanted, but then you'd have to code every button for everything you want to do. You could tell Foo to execute some method (possibly in some other Object) when it was pressed, but then you'd lock Foo and the method together. You'd have problems if someone later changed that method also, as they may not know that Foo calls it. The solution to this is to let Foo have events, and code the actual behavior in some other Object or method which handles that event.

In Java this is done through a pattern called the event-listener. I call it that, anyway. What you do is you let Foo implement a method that takes the listener (addListener(FooListener l)).

public class Foo {
private List(FooListener) listeners = new LinkedList(FooListener);

public void addListener(FooListener l) {
listeners.add(l);
}
}


FooListener is an interface that includes one method to handle the event when the listener gets it. You can put whatever you want into the FooEvent, depending on what kind of event your particular implementation raises. Often you only need to send an event, that's enough information in itself.

public interface FooListener {
public void handleEvent(FooEvent e);
}


In Foo you decide when you want to send an event to the listeners, and you do it something like this:
private void doSomething() {
for(FooListener l : listeners) {
l.handleEvent(new FooEvent("Something"));
}
}


This works, but it's a bit verbose, and worse - it's up to the developers to decide how to do this and if they will.

In .Net classes have events themselves. The engineers over at MS have taken this pattern and hardcoded it into their platform. So, what you do here is slightly different:

Events and listeners are what I know from Java, but in VB.NET they're called Events and Handlers. I can live with that, it parses. What's really cool though is that like properties (which I really like) the events are language-features. So, you've got some kind of standard to follow, it's not something you have to explore on your own or make up on the spot.

When you add a button in VB.NET your app already knows about the events that can generate (they are part of the specification of the Button class). This makes it easy for the code-generator to give you the boilerplate for a handler. In fact, that's what it does when you double-click a button in the form-designer. Coding has never been so easy, and I like that.

The problem with this easy code-generation (for me, and this may be a problem with me) is that it doesn't teach you how to do this yourself. My case was that I wanted to add a handler to a control that only exists after a certain set of actions have been taken in my program.

When I add a handler to a button which exists the code is easy. Let's say I have a button called btnFoo on my form. To handle a click from this I just type in (VB.Net):
Public Sub handleButtonFoo(ByVal sender as System.Object, ByVal e as System.EventArgs) Handles btnFoo.Click
Console.Out.WriteLine("Click")
End Sub


It gets a little more hairy when you're handling dynamically created Objects, though. This took me some time to find, and it led me to a foray into delegates. I'll get back to them some other time though.

What you have to do is create a method with the same signature as the event. Say I'm looking to handle a LostFocus event on a Control. That has the signature: Public Event LostFocus(ByVal sender As Object, ByVal e As System.EventArgs). So what I need is a method that matches that signature. Behold!

Private Sub HandleSomethingLostFocus(ByVal sender As System.Object, ByVal a As EventArgs)
Console.Out.WriteLine("Give me back my focus!")
End Sub


This is not the whole story though. You may have noticed that the handleButtonFoo method had the keyword handles after it with a reference to the event it wanted. My little lost-focus method has no such thing, as no object exists yet that I want to handle. When one exists though, I can pipe the events to my method with the following code:
Private Sub createWidget()
'Make something that can lose focus
Dim widget As New TextBox

'Add the widget to the main form (which we're in)
Me.Controls.Add(widget)

'pipe the LostFocus events to the handler we wrote
AddHandler widget.LostFocus, AddressOf Me.HandleSomethingLostFocus

End Sub


This will delegate the LostFocus events to my method. Yay!

As you may have noticed this is a better way to handle this than in Java. You get a set pattern on how to do it, defined at the language level (AddHandler is a reserved word). It's also less verbose than the Java-way, as that one included code in two classes and one interface. It may do the same, but I like it better.

Now I've got to get home, I have a sick child. Till next time!

Thursday, March 1, 2007

I'm Thinking of Something Round

I was having this little problem with the app I'm developing. It's the same program that I've been talking about the last two posts, the unnamed application I'm calling Pluto. The problem I'm addressing this time is not domain-specific however, but rather a result of my lack of experience with the platform and language I'm using.

I was looking to present parameters in a GUI for the user to manipulate. I'd solved the tasks of getting the parameters from the web service and presenting them in controls based on their type. Getting the parameters into the user's face is only half the work, though. I also had to get the user's input back into Pluto's guts somehow. Now, this gave me a few sorts of problems.

The first problem is that I know the user is interacting with a control, and I know which kind of control it is. Thus, one might think I could easily map the control-type to the parameter-type. It works, for dates, strings and booleans. It's not so easy for integers and floats though, as they're both most easily displayed with what .net calls a NumericUpDown (lovely little things). As you may know you can set the number of decimals such a control allows.

I briefly toyed with the idea of setting integer-type controls to have 0 decimals and floats to have some other number and parsing based on that. All this was starting to smell of a hack. I was taking some arbitrary subset of the data contained in a datatype (the original ReportParameter), using it to construct some other object (the Control) and then trying to make a new object of the original type with that small subset of data and some implicit knowledge (what kind of control each parameter type mapped to). Badness.

How do I get out of this bad situation I've gotten myself into? It's obvious that I want to keep the original object, and just get the changes (if any) from the control into it. That would be much better, safer, cheaper (well, not in memory but we're talking about on the order of 0-10 objects here) and much, much less buggy. Just imagine trying to maintain such a mapping if you've really no idea what I did and why...

How do I keep the original objects? One solution would be a global list of the original objects with the same numbering as the controls I added (or some other arbitrary scheme to keep the control-parameter mapping). This is not an ideal solution - it's not very object-oriented, the mapping is non-obvious and globals tend to be a bad idea for these kinds of problems. So, I kept thinking.

When I keep thinking I can come up with some really convoluted and complex solutions to problems like this. My though was this: If I make an object that includes both the original parameter and the control I can just ask it to return the parameter. The immediate problem with this is that I would loose the elegance of adding controls directly to the GUI. Could I somehow solve this by making the object an extension of the Control? If I were a .net -guru I could possibly do this in some way and easily make such an object. I am not, however, I am brand new at this platform and totally new at VB.NET. So, I looked around, read a bit, tried to understand how this plot could be hatched, but I really got nowhere.

This got me thinking about patterns, though. I like patterns, so I tried to identify what I was trying to do. Was my problem solved by a proxy? Well, no, I didn't really need an object to stand-in for another. I had access to the control, I wanted to add functionality. Could it be a composite? Not really that either, as composites are good at unifying the way you use some number (usually a substantial number) of components. It had to be a decorator, the pattern that lets you add some functionality to some existing object (by "painting" that functionality onto it). It may seem obvious now, but it's never that easy when you're thinking through it. At least it isn't for me, caveat emptor.

I had it licked. I just had to implement the pattern that "painted" the original object onto the controller. Why was I not happy? This was a tiny, but important part of Pluto, and going straight on to implementation of a decorator-pattern with interfaces and implementations et cetera wasn't what I wanted to do. I still had a hope, maybe just a wish, that I wouldn't have to go through that for this simple need.

I'd skimmed the definition of the Control to see if there was anything I could use in there at the beginning of this problem, but nothing particularly stood out. I was probably just putting off starting on the pattern, but I found myself reading through it again. I was scanning for any kind of Object-reference the Control could keep - maybe I could just put it in there? I found a few, but they all sounded like they changed the behaviour of the control in some significant manner (AccesibilityObject? No, I don't like the sound of that). Then I found it: the control has a property called a Tag, and it's an Object.

You know that combination of elation and shame you get when you see that a problem you've spent good time on has already been solved? Not only has it been solved, but it's right there in front of you ready to be used. Let me quote the description of the Tag from the API: Gets or sets the object that contains data about the control. Could it be better?

So, slightly shamed but mostly happy about the way the problem had been solved elegantly and without any implementation whatsoever I simply tagged the controls with the parameters. This means that I can get the original object directly when I parse the input from the user, get the content that's been changed and send the whole shebang back to the server.

Right now I really love that.

My professor once told me: "A few hours in a library can frequently save you months of research."

Wednesday, February 28, 2007

Time On My Mind

I'm still working on the application from my last post, Pluto. It's a rendering application for reports that connects to a reporting service (Uranus) and renders the reports to disk.

Well, I'm getting further on with the parametrized input, and I want to display the dates to the user using something a bit more apt that a simple textBox. The DateTimePicker seems to fit the bill perfectly. All I have to do is check the type of the parameter, and make one if it's a date. Simple!

Again, not so simple. I try to make a DateTimePicker and pass the default value of a date-parameter to it.

Exception!

It seems the DateTimePicker doesn't understand the string it's been passed. That's strange, I think, it must be in some kind of non-obvious format then. I fire up the debugger to look at the string directly (by the way, the debugger in Visual Studio is a dream. It really is great. Great as in WOW, GREAT!). Well, the string is in the format "1/29/2007 12:00:00 AM". Well, I can read that - why not the parser?

I'm chalking this one up to not being familiar with the .NET framework, but the way it handles dates had me stumped for a long while. I am writing this from Norway, and we usually don't use the American form of dates (month/day/year). We use the eminently superior day/month/year, which at least leads itself to some sorting. Personally I prefer the sortable ISO standard, but I realize I'm probably never getting that to fly with my wife. So, I was a bit surprised to see Uranus spit that at me (the machine is just down the hall from me, I thought it'd have the same local settings as I have. Obviously, the server-room lies on a small patch of American soil or something. No matter. When I'd figured out that the problem was with the Culture I thought I'd try to fix this in an elegant manner.

The elegant way of solving this would be to ask the ReportingService (Miranda, mentioned in the last post) what date it prefers, and gracefully use that. My plan was to delegate the parsing of it to the widget the user interacts with to keep all of the format logic out of the app itself. It's simple, elegant, it scales and it's all-around wholesome. Too bad it didn't work.

I probably spent two hours today searching for SOME WAY to get the reporting service to tell me what its preferred time-format was. I can't find it! I ended up giving up completely and just forcing conversion to and from strings internally to be done using the "en-US" format. It works, but it's hard-coding a bit of functionality that I really didn't want to hard-code.

To make for an easy fix I've at least stored the dateFormat as a global variable. That way I can go back to my original plan if someone tells me how to get the blasted service to give up the goods.

Parametrized woe

Let's set the stage. I'm developing an application in VB.NET that connects to a Microsoft Reporting Service using a Web Service.

My application (let's call it Pluto) will simply connect to the reporting server (let's call that one Uranus), get a list of reports, let the user choose one of them, let the user define the parameters of the report and render it to a file on disk. Simple, right? So I thought, or rather I thought it'd be simpler.

Now, the idea behind web services is that you can expose functionality on your platform to platform-independent apps through a well-defined protocol. That is really cool. It turns out, however, it's not always easy.

Uranus is already up and running (and in semi-production, no less) so I can't really mess with it. I am at the mercy of the setup that's already alive. I kind of like this, it's the way web services are supposed to work. So I connect to Uranus and fetch the list of reports. All is well. I let the user choose one and get the parameters to it. All is well, I get a list of parameters. I try to populate a UI with the parameters and their default values, to give the user some starting-point, and I discover that all is not well.

Uranus is exposed locally through a proxy class, so I'm working with a local object that "stands in" for Uranus. This is not really important, but kind of neat, so I thought I'd mention it. Anyway, I call methods on the proxy (let's call it Miranda) to get to Uranus. To be specific, Uranus is a ReportingService class, which delegates to Uranus.

The method Pluto is calling to get the parameters of a method is the aptly named ReportingService.GetReportParameters -method. Now this little method takes 5 parameters. That's pretty extreme to my eyes. Furthermore two of the parameters are actually arrays of objects from the same namespace. This is where my head starts to hurt.

Let's go through the parameters as they're described in msdn, my comments are in purple:
Report
The full path name of the report.
Pretty easy to understand, except it's not really the name, it's the path to the report. So, if your report is named "Bob", but it's on the path "http://Uranus/path/to/Bob" what you want to insert here is "/path/to/Bob". Naturally!
ForRendering
A Boolean expression that indicates how the parameter values are to be used. If set to a value of true, parameter properties that are returned are based on the parameter data that was used during the execution of the report.
I was a bit stumped at this one, for rendering? I'm not going to render yet, I thought, I want to get the parameters and show them to the user. Is that rendering? I thought it wasn't. Oh, did this cause me trouble...
HistoryID
The ID of the report history snapshot. Set the ForRendering parameter to a value of true in order to retrieve parameter properties for a report history snapshot. Set the value to null (Nothing in Visual Basic) if you are retrieving parameters for a report that is not a report history snapshot.
Aha! So that's what the ForRendering is for! You need it if you want a historical snapshot for some reason. I am now pretty sure I was right in leaving the ForRendering off. I just go ahead and pass a Nothing (NULL in c-like lingo) here.
ParameterValues
The parameter values (ParameterValue[] objects) that can be validated against the parameters of the report that are managed by the report server.
Now I like the kitchen sink as much as anybody, but is this really what a GetParameters should be used for? What this does as far as I can tell is that it lets you pass a set of values to this method for validation. In my meager mind some kind of ValidateParameter(ParameterValue[] p) or something would be better. It might even return a boolean, wouldn't that be nice?
Credentials
The data source credentials (DataSourceCredential[] objects) that can be used to validate query parameters.
Credentials are important. I wholeheartedly agree. I don't pass it anything yet, but I plan on later. Really, I do.
As you can probably see I was a bit confused at this method. So, I passed it the path of the report the user wanted (Name), a false (ForRendering), a Nothing (HistoryID), a Nothing (ParameterValues, I don't want to validate - I want to know what the parameters are) and a Nothing on the credentials too (hey, I'm debugging, I haven't gotten to that yet).

Success! I get a set of parameters out, and I'm smiling happily at the world. So I try to show them to the user, but they all come out as an undefined mess! They don't have default values so in effect they're just names for the parameters! That's no good for me, I have to give my users an inkling on what to enter. Hell, I even have to validate their input, how can I do that with no metadata? I go hunting for a solution.

Later, much later, I realize what my astute readers probably saw right away. Setting the ForRendering to True gives me parameters with types and default values and everything! It seems I foolishly assumed that rendering was somehow connected to what the service calls rendering in its other method. That is - the actual running of the report and output to some kind of format.

I am but a neophyte in the dark arts of web services, but I do wish they'd at least be internally consistent in their naming.

Next I'll delve into the joys of time-formats.

A small irritation in Visual Studio 2005

I'm from java-land, and I've been using Eclipse, IntelliJ Idea and NetBeans to do my development. Honestly, I was looking forward to working with Visual Studio once I got into .NET. I have to say, it's been a mixed experience. I'm probably using a tiny subset of its abilities, but there are some things about it that just drive me up the wall.

In particular I was trying to open several files/views at once in tabs, but the blasted IDE kept reusing my code-window! Argh! This is probably a minor point to anyone well versed in VS2005, but this is how you fix it:
Tools -> Options -> Environment -> Documents -> Reuse current document window, if saved (turn this off)


Oh, and make sure the window layout is set to Tabbed documents in the General section.

Tuesday, February 27, 2007

Sources

I was trying to find some sources on this .NET thing yesterday when it struck me. Podcasts!

So, I get on the almighty google, and search for .net podcasts. Lots of other stuff pops up, but one seems genuinely interesting. The podcast is called .NET Rocks!, and it piqued my interest at one particular item.

They've interviewed Venkat Subramanian and Andrew Hunt on Agile. These two have written a book I've been reading lately, Practices of an Agile Developer. It's a tour of good practices and gotchas of agile development, and I really do recommend it. I got it as a gift for helping with the running of the ROOTS conference here in Bergen, Norway last year.

So, naturally, I got the feed and downloaded a couple of the more interesting-sounding shows to my player (no, not an iPod, it's a Zen). This may turn out to be a long and happy listenership. It seems .NET -developers are a really fun and happy bunch (well, judging from the shows I've heard so far). Maybe this won't be painful after all...

Quote of the day:
I used to tell my students that if you are just starting out in .NET your boss is going to be giving you a little bit of leeway but your boss would better spend their money by sending you to the beach with the specs for the System .NameSpace. Just have you read it for a week because you are going to make up that time many, many times over by knowing that what you’ve done.
-Carl Franklin

My Personal Journey

Hello, and welcome to my log of things I learn as I enter the wonderful world of .net

Some background: I am starting this blog as a way to document my experiences with a new environment, framework, job and language(s). This is the result of me getting a job as a developer on the .NET -platform, primarily using VB.NET and ASP.NET (but I hope to be able to sneak in some C# as well on some later date).

My experience this far has been primarily with Java, with some ML and assembly thrown in to make my education rounded. In short - I am fresh out of University, and I'm experiencing firsthand the differences between an educational and an enterprise setting.

The reason I'm starting this blog is that I feel I'm learning things all the time. They may seem small and inconsequential to experienced .NET developers, but they're important in my life. I'll try to form posts from my small nuggets and post them here. If I can.