A collection of learnings and opinions.

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.