Saturday, December 31, 2005

Looking Forward to 2006, Looking Back on 2005

As is my custom, I like to take a look back at the end of the year and check out what happened. I'm bringing y'all along for the ride.


Reviewing my blog, I see that I had one goal for 2005: ship FlexWikiPad 1.0. Well, that didn't happen. In fact, I didn't even do any significant work on it. Why not? Because I managed to push a couple of major projects onto the stack on top of it (bet you've never done that ;). For one thing, it seems I have to write a whole new text editor control (something I also didn't finish this year). But more significantly, I decided to completely overhaul the FlexWiki internal architecture to make it possible to implement security in a sane way.


Of course, I didn't finish that, either, but then again I didn't expect to. It's a pretty big job to do in my spare time, and along the way, it morphed into a decision to port FlexWiki to .NET 2.0. That is actually coming along fairly well, especially now that I try to spend an hour every day working on it. With luck, I'll have something to alpha status in month or two more.


It wasn't all FlexWiki work this past year, though. I had paying clients, too. My work at Integic redesigning and updating their main product has, after three years, reached code complete status. That's fairly exciting for me, because as a consultant I rarely get to see a project through from the very beginning. Even more interestingly, it looks like I'll be involved in working on the next phase as well, which means I'll get to see if some of our choices wind up helping us out like we hoped they would.


My other work in 2005 is still ongoing. I'm developing Pluralsight's new architecture course, for one. The research for that has been very educational, as I knew it would be. Hopefully I'll be able to pull the rest of the class together over the next few months.


Of course, my work on MSDN2 continues as well, but I can't say much about what I'm working on just yet. When we get it in place, you'll definitely hear about it, both here and elsewhere. I think it's something that readers of this blog will find interesting.


As you can see, 2006 is looking to be every bit as busy as 2005 was…and then some. I'm just glad my wife will be graduating from her MBA program in the spring.


I'll close with a list of my favorite/most significant events/posts of the year:

















  • I became a whore for rent. You should see the Google searches that post gets. :)







  • November was not a great month. Could have been worse, though. A lot worse.

  • I ran into this problem, which would have bitten me several times since if I hadn't gotten help from one of my smarter (specifically: smarter than me) friends.



Friday, December 16, 2005

sqlcmd.exe -v Rocks

I'm the first to admit that I'm no database guru, but I occasionally have need to do something beyond just a simple SELECT, and I can usually manage to fumble my way through it.


The other day, the thing I was fumbling my way through was restoring a database from a backup a client had sent me. While I was doing it, I ran across a neat little option to sqlcmd.exe that I hadn't seen before, but which I definitely want to remember. It's the -v option, and it lets you pass parameters to your SQL script. In my case, I wanted to pass the current directory, so I could restore the database to files in whatever directory I happened to be running. Well, putting this in a .cmd file does the trick:


sqlcmd -E -i restoredb.sql -v root="%CD%"


Then I can use the root variable in my SQL script. All I have to do is reference it with the $(root) syntax, like this:


    FROM DISK = '$(root)\mydb.bak'
    MOVE 'mydb_data' to '$(root)\mydb.mdf',


Nifty, eh? I know I'm far from the first one to "discover" this, but maybe it'll help someone who hasn't seen it before.

Thursday, December 15, 2005

Using a Custom WSDL File in ASP.NET Web Services

Some of the work I'm doing right now involves writing a web service that has custom WSDL. By "custom" I mean "written by hand, not generated by the ASP.NET web services infrastructure". In this case, it's because we've got a bunch of external schema types that we'd like to use in a certain way, but you might want to do the same thing for a variety of reasons, including just not liking the way the generated WSDL looks.


As it turns out, using an external WSDL is fairly easy. It's just a little obscure - I had a hard time tracking down how to do it using Google, so I'm documenting the process here. Following, the steps required:


Write a custom WSDL file.

Use the tool of your choice. The one thing you're going to want to do is to omit the <wsdl:service> declaration. This bit actually will be generated by the ASP.NET infrastructure. That makes sense, since it contains a URL, and can be more easily determined at runtime.


Drop the WSDL in the web directory next to your .asmx file.

Presumably, you still want people to be able to download your custom WSDL, so putting it somewhere web-accessible is a good idea.


Mark your web service implementation class with the [WebServiceBinding] attribute.

For instance, you might do something like this:


[WebServiceBinding(Name = "MyBinding", Location = "MyCustom.wsdl")]
public class MyServiceImplementation : WebService


// ...



The most important thing to set here is the Location property, which tells ASP.NET where your custom WSDL file lives. The Name property gives the name of the <wsdl:binding> from your custom WSDL, and is needed by ASP.NET to allow it to dispatch calls onto your implementation correctly.


Mark your web method with the [SoapDocumentMethod] attribute.

For example:


[SoapDocumentMethod(Action = "urn:foo-com:service/DoSomething",

Binding = "MyBinding")]

public DoSomethingResponse DoSomething(DoSomethingRequest request)


// …



The Action property associates this method with the action listed in your WSDL file. It is particularly important because ASP.NET chooses which method to invoke based on the action in the incoming message.


The binding element associates the operation with a particular <wsdl:binding>, in much the same way that the Name property of the [WebServiceBinding] attribute does. It’s required to be on the [SoapDocumentMethod] attribute for proper operation, but I still haven’t quite figured out why you need both.


Observe the generated WSDL.

If you surf to the automatically-generated WSDL page (e.g. http://server/path/to/service.asmx?wsdl), you’ll observe that ASP.NET is still generating a WSDL document for you. However, because of the changes you’ve made, that WSDL consists solely of a <wsdl:import> referencing the WSDL file you wrote, and a <wsdl:service> element containing the URL for the service. It’ll look something like this:


<wsdl:definitions targetNamespace="urn:foo-com:service">

<wsdl:import namespace="" location="MyCustom.wsdl"/>



<wsdl:service name="MyService">

  <wsdl:port name="MyBinding" binding="tns:MyBinding">

    <soap:address location="http://localhost /MyService/MyService.asmx"/>


  <wsdl:port name="MyBinding1" binding="tns:GetContentBinding">

    <soap12:address location="http://localhost/MyService/MyService.asmx"/>






Luckily, Add Web Reference respects the <wsdl:import> and (assuming you write the WSDL correctly), .NET clients will be able to generate code off of this document successfully. Other toolkits should be able to as well, but YMMV.


Particularly when coupled with the flexibility that IXmlSerializable gives you over the serialized XML, taking control of the WSDL is a very powerful technique.

Friday, December 9, 2005

C# Type Conversion Operators Considered Harmful

I see Fritz just posted a code sample that makes use of C# conversion operators. I don't like it. No sir, I don't like it one bit. :)


Here's the deal. A conversion operator is just a way of writing a method that you invoke using the C# casting syntax. The thing is, since it's a method, why not just make it a method. If I were writing this code, I'd call it ToUpdateItem() or perhaps emphasize its a factory nature by calling it something like CreateFromUpdateItem.


There are two problems with the type conversion operator approach as I see it. First, you're providing something that implies type compatibility, when really no such type relationship exists. Second, the conversion operator syntax implies that no new instance is created, when in fact a new object instance is created every time.


With a plain ol' method, people who maintain your code can see exactly what's going on. With a type conversion operator, you're just twisting the language syntax to make it look like one thing is happening, when really something else is.


A good rule of thumb is that if you see yourself typing "public static operator", you're doing something wrong. :)

Friday, December 2, 2005

FlexWiki Released

I just posted the latest version of FlexWiki over on SourceForge. You can download it here. Here are the release notes:


This release is primarily a bugfix release, although several minor
features have been added. Basically, the fixes were piling up, and we
were telling people "go download the latest interim build" often
enough that we decided just to make it official. Highlights of this
build include:


* At long last the death of the "incorrect wiki links" bug, where
  FlexWiki emitted links that corresponded to the first hit after
  startup. This most frequently manifested itself as links pointing to
  "localhost" even when the web server was accessed remotely.
* Null edits are now ignored.
* Slight performance enhancements, including the ability to turn off
  performance counters (which can cause large delays on some
  installations) via the DisablePerformanceCounters switch.
* Form support in WikiTalk


And much more.


Thanks to everyone that contributed, both those who wrote code and
those who reported bugs!


Please direct inquries about FlexWiki to the FlexWiki users mailing
list at

I definitely recommend that you upgrade to this release if you're currently running


I'm guessing this will be the last official release of FlexWiki before 2.0. (You can always get unsupported interim releases from I've been working away in my spare (ha!) time on gutting and rearchitecting the content engine, and I've been making slow but steady progress. It'll probably be a few months before I get it to alpha status, but once there I should be able to start making rapid progress on implementing security and some caching improvements.