Enterprise Library Lightning Talk#

If you're coming to the DevDays (err "Developer & IT Pro Days", sorry, force of habit) in Belgium this week, don't miss the Community Evening on Tuesday!

One of the things happening there is the Lightning Talks Session, where different speakers can spend a whopping 5 minutes on a Microsoft related subject. Thanks Bernard Vander Beken for organizing these!

I'll be giving a quick intro to the Enterprise Library (entitled "Citations from the Enterprise Library") that was just released, so if you're there, come say hi!

Blog | Programming | .NET | EntLib
Monday, January 31, 2005 12:47:45 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 



I love the smell of paper...

All this fuss about the Moleskine notebooks (It Rocked My World!, My 21st Century PDA!, Moleskine Hacks!, etc.) is making me very curious.

I'd go buy a pocket plain notebook, but the nearest dealer appears to be in Amsterdam... Does anyone in Belgium have one of these and coming to DevDays to show me?

Sunday, January 30, 2005 12:45:16 PM (Romance Standard Time, UTC+01:00) #    Comments [6]  | 


ASP.NET Comments#

I've just expressed my love for comments (which generated some interesting discussion as well) and a while ago I've been quite active in ASP.NET 2.0; so let me take the opportunity to raise a personal concern of mine when combining the two.

Remember that one goal of ASP.NET 2.0 was to reduce the code needed for typical scenarios by 70%. That's a lot and I don't have any metrics yet, but they've certainly managed to eliminate a lot of keypresses that I hope I will never need to break my fingers on again. They've also overhauled the databinding system (just look at the ObjectDataSource) to reduce code and you can even use the Web.config file to declaratively create a strongly-typed Profile, or couple all your pages to a common basepage to include boilerplate code.

So great! With all this, ASPX has definitely become a double-JITted programming language of its own - as Early & Adopter so beautifully put it during the last PDC.

The only problem I have with it, is that when hiding more and more code behind markup, where do we document what we're doing? We don't. Do you? Thought so... So come on, be nice: comment your markup when it gets anywhere near semi-complex.

And don't just write <!-- html comments --> either, but be sure to use the <%-- server-side comments --%> in ASP.NET, since they don't get sent out to the browser (which would increase your final page size and possibly even leak information about your business logic to the browser for everyone to see).

Still, this doesn't do anything to promote itself as metadata (that can be used by tools) like the well-known XML comments, so it's still fairly useless apart from serving as in-line documentation. But then again, if you're writing structured code that needs structured comments, you should really put it in code anyway, and not in markup.

Blog | Programming | .NET | ASP.NET | Whidbey
Monday, January 24, 2005 8:04:35 PM (Romance Standard Time, UTC+01:00) #    Comments [2]  | 


Upgraded to dasBlog 1.7!#

I couldn't wait to upgrade to the new 1.7 version of dasBlog Community Edition (as it's called nowadays) because of all the great new features: far better performance, anti-spam measures, drafts (finally!), and lots more. Three cheers to Omar Shahine, Scott Hanselman, and everybody else who dedicated some precious time to it!

Unfortunately, there seems to be a small bug in the drafts functionality, since posts that aren't marked as Public (i.e. drafts) still show up in the RSS feed. Whoops ;-) I'll be keeping an eye on the bug I submitted to the SourceForge tracker because I really want to start using drafts... Update: My eyes must be deceiving me, the draft version of this post worked perfectly without showing up in the RSS feed... It did fail on my test machine though... Anyway, I'm sure it was my fault then.

If you're planning on upgrading too, you'll notice that you have to run an upgrade tool against your contents directory. The fix for the "Comments may disappear when moving content across GMT timezone boundary" bug I briefly mentioned before and submitted to Omar Shahine may have something to do with that since I believe that triggered the filename changes, sorry about that ;-)

Still, I had a little problem upgrading my content, and I believe it's related to that bug. I pulled the content from my server (which is on time zone GMT-7) to my machine (GMT+2) and ran the upgrade tool. Everything seemed fine on my test machine, but I noticed that the comments on some (what appeared to be) random posts had disappeared. I dug a little deeper and noticed these posts were submitted quite early in the night so I suspected a time zone issue again. I reflectored (uhm, yes, that's a word) the upgrader exe to see what it was doing and I noticed it was using the local time zone for some date-time calculations. So on a hunch I switched my local timezone to the one of my server and everything worked just fine. Whew :-)

So here's a word of advice: if you upgrade your content directory, be sure to temporarily set your local machine to the same time zone as the server the blog will be running on!

Blog | General | Programming | .NET | ASP.NET
Sunday, January 23, 2005 4:25:38 PM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 


The Corporate Blogging Question#

I've hardly been home at all this week so David scooped me: I've just started working as a .NET consultant and technical coach for the Belgian Compuware .NET team today! Thanks for the warm welcome, David, and a big thanks to the rest of the Compuware team as well! I'm looking forward to working with you all! As it goes, I already have one anecdote I'd like to share with the blogging community here.

As it happens, Irene Dawson, the Senior Vice President of Compuware EMEA, was at the Belgian office today for a visit and a talk. There was room for some questions at the end of her talk and there was a tricky one in there: "what's the corporate policy towards blogging?". Good one, I might add. Who knows, maybe I'm already violating it here ;-)

So forget what you know from your "little" inner circle here on the big semi-organised chaos that we call the "internet", but blogging still isn't known to everybody out there in real life :-) So as she was trying to assimilate the meaning of this new word, my new manager pointed her at me on my first day to quickly explain blogging to her on the spot. I think I managed to get some of its intricacies into her mind but a little preparation would've been nice though ;-) So I'll be explaining her the meaning and issues some more in detail through email; any definitions and precedents to help set the stage are welcome. Robert Scoble's Corporate Weblog Manifesto is already on the list but I'd like some more diverse viewpoints actually...

Anyway, I'd heard a lot of nice things about Irene so it was great to meet her at last (she's a very warm and vibrant person) and she'll probably remember me as "the blogger" or something, but it was fun nevertheless :-) I guess it's one way to meet your Senior VP on your first day...

Thursday, January 20, 2005 1:16:53 AM (Romance Standard Time, UTC+01:00) #    Comments [4]  | 


XML Comments Quick Reference#

I'll come out and bluntly admit it: I don't mind writing XML comments in my code. Really. I can get pretty freaky about it too if you let me, and I always try to make sure that every comment is kept in sync with the code it's covering. Why? Because if you make the compiler (or a 3rd party tool for those languages that don't support it) emit an XML comments file, it gives you free and up-to-date IntelliSense and even full-blown technical documentation, duh!

So if you're also constantly lost in the MSDN documentation trying to figure out which tags are allowed and what the syntax is, here's a quick reference for your amusement. Now start writing comments, please!

Documentation Sections

  • <summary>

    A short description of the item; describe the members of the type here.


  • <remarks>

    The "Remarks" section of the documentation; specify overview information here.


  • <example>

    The "Example" section of the documentation.


  • <seealso>

    A link in the "See Also" section of the documentation.

    <seealso cref="member">text</seealso>

Member Documentation

  • <param>

    Describes a parameter to a method.

    <param name="name">text</param>

  • <returns>

    The return value of a method.


  • <exception>

    The exceptions that can be thrown.

    <exception [cref="type"]>text</exception>

  • <value>

    Describes the value of a property.


  • <permission>

    The permission applied to a member.

    <permission [cref="type"]>text</permission>

Text Formatting

  • <c>

    Format characters as code within other text.


  • <code>

    Multiline section of code.


  • <see cref>

    A link to a type, member or field in the current compilation environment.

    <see cref="member">text</see>

  • <see langword>

    Undocumented. A link to a keyword in the language of the current compilation environment, e.g. null.

    <see langword="keyword"/>

  • <paramref>

    A reference to a parameter within other text.

    <paramref name="name"/>

  • <list>

    A list of items.

    <list type="[bullet|number|table]">

  • <para>

    A paragraph within other text.


  • <include>

    Refer to comments in another file.

    <include file='filename' path='tagpath[@name="id"]' />
Blog | Programming | .NET | VS.NET
Sunday, January 16, 2005 11:00:38 PM (Romance Standard Time, UTC+01:00) #    Comments [14]  | 


Short Story: "El Viaducto"#

A while ago, I followed a weekend course on shorty story writing, which was really fun to do! Not only did I get to learn some interesting theory around writing and how stories are built up, but of course we were supposed to write something as well.

I started from an object (a weird sort of sunglasses), mixed that with a location I just visited (Madrid and a specific bridge I remembered from there) and let my imagination do the rest. We gradually built the story up as we learnt more and more and at the end of the weekend I had a nice little story. After some rework and a feedback session and some more rework I think I'm pretty much finished so here goes (Dutch only I'm afraid)...

El Viaducto

Let me know what you think!

Blog | General | Stories
Saturday, January 15, 2005 6:42:13 PM (Romance Standard Time, UTC+01:00) #    Comments [2]  | 


Binding the child rows of a DataRow#

Either I'm missing something or the ADO.NET team missed a fairly simple scenario... Imagine you have a single DataRow out of a table with a relation to another table. Now you want to bind a DataGrid (e.g. WinForms but that doesn't really matter here) to the child rows of that DataRow. Sounds easy, right?

And sure, there's a handy GetChildRows method that returns an array of child rows for a given relation. Unfortunately, binding a grid to an array will make it display the properties of the DataRow object, not the actual content of the DataRow.

So you need some way to get something bindable out of that parent row. You might create a new DataTable with the same structure and load it with the child rows but that's pretty cumbersome.

If you have a DataRowView, then you can get a bindable DataView out of it using the CreateChildView method. Although you can't lookup or create a DataRowView directly, you can get it by looping over the DefaultView of the associated table. This is how it could roughly look in code:

public DataView GetChildView( DataRow parentRow, DataRelation relation )
    // Find the associated DataRowView of the parent data row.
    foreach( DataRowView rowView in parentRow.Table.DefaultView )
        if( rowView.Row == parentRow )
            // Create a child view through the DataRowView and the relation.
            return rowView.CreateChildView( relation );
    // No associated DataRowView found.
    return null;

Now the resulting DataView can easily be bound to a datagrid.

Friday, January 14, 2005 6:13:38 PM (Romance Standard Time, UTC+01:00) #    Comments [2]  | 


Tiny but great DataSet change in Whidbey#

There's a quite lengthy post from the VB team about the data design time changes between Whidbey beta 1 and beta 2 (via 3Leaf Development).

In there, I found a little gem that will solve one particular annoyance I have with the current Typed DataSet generator: while the columns are generated as strongly typed objects, they're declared as internal so they're no use outside the declaring assembly. Hence the column names in quotes in my previous posts about DataSets and Web Services:

testData.Employee.Columns["ID"].ColumnMapping = MappingType.Hidden;
testData.Employee.Columns["CompanyID"].ColumnMapping = MappingType.Hidden;

This will fortunately change in Whidbey, allowing more strongly-typed and thus safer code:

testData.Employee.IDColumn.ColumnMapping = MappingType.Hidden;
testData.Employee.CompanyIDColumn.ColumnMapping = MappingType.Hidden;

I had planned a rant on that but it seems I've been pre-empted by the team that figured it out on their own :-) At least, if the C# team is also doing this but I can hardly imagine that they wouldn't follow the pattern here. It's the small things that can really make a difference you know...

Blog | Programming | .NET | VS.NET | Whidbey | Samples
Thursday, January 13, 2005 10:08:58 AM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 


Pushing modified DataSets through Web Services#

There seems to be a bug in the .NET Soap serialization stack when passing a DataSet with an expression column in it that uses a relation. Allow me to elaborate :-) But don't run off just yet if you don't care about the serialization stack, there's some useful stuff in there as well ;-)

Imagine a typed DataSet "TestDataSet" that you're passing from your Service layer to your client UI layer through an ASP.NET Web Service. Say you have a table Employee and a table Company in it, and you want to show the employees in a DataGrid (e.g. WinForms but that doesn't really matter here) with the name of the company in a separate column. The service backend doesn't care about your needs to display the company name inline with the rest of the data, so all you have is the relation CompanyEmployee between the two tables.

For display purposes, you can add a column to the Employee table with its Expression set to "Parent(CompanyEmployee).Name" and it will display just fine: it calculates the new column by navigating to the parent row through the CompanyEmployee relationship and then takes the Name column from that row. Bingo!

TestDataSet testData = TestServiceAgent.GetTestData();
testData.Employee.Columns["ID"].ColumnMapping = MappingType.Hidden;
testData.Employee.Columns["CompanyID"].ColumnMapping = MappingType.Hidden;
testData.Employee.Columns.Add( "CompanyName", typeof( string ), "Parent(CompanyEmployee).Name" );
employeeGrid.DataSource = testData.Employee;

Extra advantages: this value is automatically updated if the parent changes and since it's a calculated column, you can't edit the company name in the grid. Also note that you can hide columns by setting their mapping type to Hidden. That's just a simple trick you can use on the client side.

The problem arises when you use this modified DataSet to update your entity in the backend again: you probably have some SaveTestData method on your service that accepts a TestDataSet to be saved and you just want to pass the changes of the modified DataSet along to it.

TestServiceAgent.SaveTestData( testData.GetChanges() );

Too bad, it will blow up in your face:

Exception: System.Web.Services.Protocols.SoapException: Server was unable to read request. --->
System.InvalidOperationException: There is an error in XML document (1, 12311). --->
System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Data.LookupNode.Bind(DataTable table, ArrayList list)
   at System.Data.DataExpression.Bind(DataTable table)
   at System.Data.DataExpression..ctor(String expression, DataTable table, Type type)
   at System.Data.DataColumn.set_Expression(String value)
   at System.Data.Merger.MergeSchema(DataTable table)
   at System.Data.Merger.MergeTableData(DataTable src)
   at System.Data.Merger.MergeDataSet(DataSet source)
   at System.Data.DataSet.Merge(DataSet dataSet, Boolean preserveChanges, MissingSchemaAction missingSchemaAction)
   at TestProject.TestDataSet.ReadXmlSerializable(XmlReader reader) in C:\TestProject\TestDataSet.cs:line 166
   at System.Data.DataSet.System.Xml.Serialization.IXmlSerializable.ReadXml(XmlReader reader)
   at System.Xml.Serialization.XmlSerializationReader.ReadSerializable(IXmlSerializable serializable)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read14_SaveTestData()
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
   at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
   --- End of inner exception stack trace ---
   at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
   at System.Web.Services.Protocols.WebServiceHandler.Invoke()
   at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
   at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message,
WebResponse response, Stream responseStream, Boolean asyncCall)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
   at TestProject.TestServiceProxy.SaveTestData(TestDataSet testData) in c:\testproject\testserviceagent.cs:line 291
   at TestProject.TestServiceAgent.SaveTestData(TestDataSet testData) in c:\testproject\testserviceagent.cs:line 162

As you can see, the Soap/XML deserialization stack has some problems with the expression column. And this isn't just because the parent row could be missing in case you only sent the changed rows (which you should do using the GetChanges() method on the DataSet to get the diffgram): it happens even if you send the full DataSet back. If there's an expression column that doesn't use a relation, then there's no problem.

There's a post on .NET 247 called "Serialize DataSet with ExpressionColumn" that shows somebody else running into this issue, and if you kept your foreign languages polished you can also check it out on the Russian GotDotNet site. But that's all I found on it so far, and none offer an explanation or solution.

A possible workaround would be to remove all expression columns again before submitting the DataSet back to the Service layer, but that's pretty harsh, not too transparent, and it can mess up your UI if you're still using the DataSet on-screen.

What I consider to be much better, is to create a new instance of the typed DataSet and merge the changes of the DataSet you're working with into it - making sure you ignore anything not in the DataSet's schema by using MissingSchemaAction.Ignore. This removes all the added clutter you don't need on the backend anyway and it makes sure you get a clean and valid copy of your typed DataSet out of the door.

TestDataSet changes = new TestDataSet();
changes.Merge( testData.GetChanges(), true, MissingSchemaAction.Ignore );
TestServiceAgent.SaveTestData( changes );

This way, everything works and the universe is happy again.

And if you're worried about the cost of the extra DataSet you just created: it's on the client side so I'd consider the performance hit negligible as long as you don't constantly send this type of changes to the backend. Then again, if you are constantly doing this, then there's probably something wrong with the way you're using your service :-p

Wednesday, January 12, 2005 2:31:23 PM (Romance Standard Time, UTC+01:00) #    Comments [5]  | 


Fixing the IExtenderProvider in ASP.NET#

Very, very cool: Fixing the IExtenderProvider in Visual Studio's ASP.NET designer.

The fact that Extenders Providers don't work in ASP.NET has been bothering me for a very long time, and this article shows a way how to fix that once and for all. And all it needs is an extra attribute on your IExtenderProvider class. Sweet!

In case you're wondering: extenders aren't supported in ASP.NET because the team didn't really see a scenario for it. Mainly because they're mostly used to hook into control events and that just doesn't really happen as much on ASP.NET like in WinForms.

But you could still do useful things with it (translation and data binding jump to mind) so I was really bummed about that. I talked to Scott Guthrie about it on the PDC03, explained a few reasons why I'd use them and he agreed I had a good point but it was unlikely that they would actually implement it.

Blog | Programming | .NET | ASP.NET | VS.NET | PDC03
Tuesday, January 11, 2005 12:58:40 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 


Avoiding WebSite_1 when pulling an ASP.NET Site from SourceSafe#

Today was frustration day. I got all cooked up a few times and got mad at

  • my next-door neighbour (for playing loud music at 2:30 AM)
  • some printer (for paperjamming 66% of the time)
  • Visio (for generally sucking; well either that or I'm just too much of an idiot to understand how to properly draw a UML sequence diagram in there)
  • aspnet_wp (for not finding some system dll's in its own runtime cache until I nuke the process)
  • SourceSafe (see Visio; and for the reason below)
  • Visual Studio .NET 2003 (for pestering me with the "Object type cannot be converted to target Type" CopyLocal bug again)

Luckily, I also picked up what could be the trick to avoid an all-too-common SourceSafe mess.

If you're getting a new solution from SourceSafe that includes an ASP.NET Web Site or Web Service you probably encountered this as well: chances are that you don't keep your sources under IIS's wwwroot but under your local SourceSafe working directory and then create VRoots (Virtual Roots) in IIS to the proper directory. If you did that before you opened the solution in Visual Studio .NET for the first time, you're doomed with a feeble attempt of SourceSafe to create the web for you, again. It notices that there's already a web with that name, creates a new one with the same name and a "_1" suffix and then complains that it can't bind to the proper web site. Here's a trick that worked for us:

  • Create the directory but keep it empty (don't get a local copy out of SourceSafe)
  • Create the VRoot to that directory with the proper name
  • Make sure Anonymous Access is enabled on the VRoot
  • Open the solution in Visual Studio .NET, SourceSafe should be getting the files in the right directory now
  • Disable Anonymous Access on the VRoot if required

If you have other or better solutions, don't hold back and share them :-) I've seen a trick via David to avoid some other problems by making SourceSafe treat a web project as a class library, but I think the friction is pretty high on that one.

And I'll still be holding my breath for the source control system included with Visual Studio 2005 Team System of course. That, and the fact that Visual Studio .NET 2005 doesn't need IIS anymore, or creates web sites under wwwroot by default. Shoosh, now be gone SourceSafe.

Monday, January 10, 2005 10:09:55 PM (Romance Standard Time, UTC+01:00) #    Comments [4]  | 


3rd Belgian Geek Dinner: 21 January 2005 @ Brussels#

Whaddayamean, you haven't let Roy know that you're coming to the 3rd Belgian Geek Dinner yet? Well what are you waiting for!

This time, it's going to be in Brussels so no more excuses about the heavily feared construction site that is Antwerp! It looks like there's gonna be a fun gang so just come over, have a great Mongolian Barbeque and hang out with your fellow geeks!

Hope to see you there!

Thursday, January 6, 2005 5:14:25 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 


All content © 2015, Jelle Druyts
On this page
Top Picks
Total Posts: 351
This Year: 0
This Month: 0
This Week: 0
Comments: 530
This is my personal website, not my boss', not my mother's, and certainly not the pope's. My personal opinions may be irrelevant, inaccurate, boring or even plain wrong, I'm sorry if that makes you feel uncomfortable. But then again, you don't have to read them, I just hope you'll find something interesting here now and then. I'll certainly do my best. But if you don't like it, go read the pope's blog. I'm sure it's fascinating.

Powered by:
newtelligence dasBlog 2.3.12105.0

Sign In