Wednesday, July 28, 2004

Wiki and Wiki; What is Wiki?!?

I've had a number of people talk to me lately about wikis, and from these conversations it has become clear to me that at least a few are unclear on what they are about. So, I'll take a stab at defining them.


First and foremost, wikis are about authoring a set of static HTML pages. That's it. If you're trying to do something with a wiki that would be hard to do well with a set of free form HTML pages written using Front Page, then you probably won't do it well with a wiki. A great example of this is discussions: wikis pretty much suck at threaded, back-and-forth conversations, because free form, static web pages pretty much suck at this. Note that more constrained or more dynamic web applications might still do a decent job (think message boards), but a big ol' pile o' HTML is a long way from being a discussion board. 


Still, for all the things it isn't good at, there are lots and lots of useful things you can do with a set of hyperlinked HTML pages. So why wiki? Well, a wiki gives you two things:



  1. Collaboration.

  2. A simple authoring language.

The collaboration one is the one you generally hear about most. The idea that lots of people can walk up to your website and author their very own page, or even edit one that you wrote is totally crazy-sounding, but turns out to be immensely powerful.in a lot of situations. Of course, because we can't trust everyone not to deface the shared page, most (not all) wiki engines offer version control to make it easy to undo what others have done, but I don't think version control is really central to the Zen of wiki.


However, I happen to think that the other major facet of wikis is every bit as important as the first: the fact that they introduce a simple authoring language. For example, if you look at the language that FlexWiki offers, it's simple do make something bold - you just *surround it with asterisks*. The wiki engine then interprets this into HTML that makes the enclosed text bold when the page is viewed. While this isn't much simpler than surrounding the same text with the equivalent <b> tags, it turns out that this syntax (and the other syntactic elements a good wiki language offers) are just _enough_ simpler to lower the bar on contributions to the point where people are actually willing to spew their brains onto a page. 


It really says a lot about human laziness that harnessing its power can do so much. :)

Tuesday, July 27, 2004

DefaultValue and XmlSerializer Don't Mix?

Maybe someone can explain to me why this:


using System;
using System.Xml.Serialization;


public class Foo {
  [XmlAttribute]
  [System.ComponentModel.DefaultValueAttribute("three")]
  public string value = "three";
}


public class App {
  public static void Main() {
    XmlSerializer ser = new XmlSerializer(typeof(Foo));
    Foo foo = new Foo();
    ser.Serialize(Console.Out, foo);
  }
}


produces this:


  <Foo />


whereas if you remove the DefaultValue attribute, you get this:


  <Foo value=”three” />


which is what I would expect. This is particularly troubling, since wsdl.exe will generate proxies that use System.ComponentModel.DefaultValueAttribute when it sees schema types with fixed value constraints.


I have to assume this is a bug in System.Xml.Serialization, but I'm willing to believe that there's some subtlety I've missed. I've confirmed this behavior in CLR 1.1 and 2.0.40607.

Sunday, July 25, 2004

I Won't Miss It

Via Tim Bray, this amusing little story about how IE is not quite as universal as it once was. I for one, wouldn't miss it for a second if it went away tomorrow: I use Firefox, which is far superior.


Actually, I would miss it a little, but only because there are a few important sites that are busted in anything but IE. Sadly, all FlexWiki sites fall into this category (but hopefully not for much longer).

Saturday, July 24, 2004

Mixing Forms and Windows Authentication

A client of mine wants to provide single sign-on (SSO) capabilities in their web application, so that users don't have to type in their domain password when authenticating to the application. The twist? Only some users of the application use SSO: the rest have accounts that exist only in the application database. So we couldn't just flip on “integrated authentication” in IIS and party on. But with the help of Keith Brown, I was able to figure out a pretty nifty solution.


The trick was realizing that if you enable both “anonymous“ and “integrated“ authentication for a particular virtual directory, the browser won't try to authenticate to the web server until it receives a 401 (Unauthorized) back from the web server. But you can issue your own 401 any time you like! So what I did was to just set up Forms authentication as normal, but also provided a checkbox on the login form that said, “Use my network credentials.” Then, in my login form, I did something like this:


public class Login : Page {
  protected
Label ErrorMessageLabel;
  protected
TextBox UsernameTextBox;
  protected
TextBox PasswordTextBox;
  protected
CheckBox CheckBox1;

  public void Page_Load(object
o, EventArgs e) {
    if
(IsPostBack) {
      string authenticatedUser = null
;
      if (CheckBox1.Checked)
// Use their network credentials
     
{
        string
user = Request.ServerVariables["LOGON_USER"];
        if (user.Length == 0)
// They haven't provided credentials yet
       
{
         
Response.StatusCode = 401;
          Response.StatusDescription = "Unauthorized";
          Response.End();
        }
        else
// They have
       
{
         
authenticatedUser = user;
       
}
      }
      else
// Use the username and password they provide
     
{
         if
(IsPasswordOK(UsernameTextBox.Text, PasswordTextBox.Text)) {
          authenticatedUser = UsernameTextBox.Text;
        }
      }
      if (authenticatedUser != null)
// They authenticated successfully
     
{
        // Issue the Forms Auth cookie and send them on their way

        FormsAuthentication.RedirectFromLoginPage(authenticatedUser, false
);
      }
      else
// They didn't
     
{
       
ErrorMessageLabel.Text = "Invalid username or bad password. Please try again.";
     
}
    }
  }
}


What this does is - when the user submits the login - check to see whether they want to authenticate by providing a username and password (normal Forms authentication) or whether they want to authenticate automatically, using their logged-in credentials. Right now, I'm figuring this out by having them explicity check a checkbox, but I do lots of other things. For example, I could have them always enter their username, and then go look in the database to see whether they're supposed to get a SSO login or a normal one. Or I could have them check the checkbox once and remember their settings forever after in a cookie.


Whatever mechanism I decide on, the trick here is that I can force the browser to authenticate by sending back a 401. Then, in subsequent visits, I can check the LOGON_USER server variable to see if the authentication was successful or not. If it is, I'm perfectly welcome to issue them a valid Forms Authentication login, secure in the knowledge that the user has proven knowledge of their password to IIS already.


If the user is using IE, the authentication will happen automatically, using whatever credentials they're logged in to the client machine with. It works in Firefox, too, but they get that little username/password popup dialog box. Oh well - maybe the Firefox people will add auto login in a future release, or someone will write an extension. But failing that, providing SSO only to IE users is good enough for us.

Friday, July 23, 2004

Keith Brown Seeks Help - See Your Name Up In Lights

Keith was helping me out with an interesting security problem yesterday (more about that in another post), and he pointed me to his online book as a resource for some code I needed. I'd read almost all of it already, and we fell to talking about how it would be to port it to a wiki format. After all, it's a series of interconnected pages that occasionally need to get updated, which is pretty much the definition of what a wiki is good at.


Well, I wake up this morning and discover that he's already started moving the darn thing over. And he's looking for your help to finish porting it. I've already signed up to help - you should, too: being part of distributing good information about security is a community service.

Wednesday, July 21, 2004

MIT Grad Wins Miss Massachusetts

While others may have different preconceptions about women at MIT, I've always known there are some great-looking women there...after all, I married one. Now, an MIT grad has won Miss Massachusetts and will compete in the Miss America pageant. The coverage here is a bit condescending, but her take is interesting nonetheless.

Tuesday, July 20, 2004

Announcing the Pluralsight Wiki

Being as involved as I am in FlexWiki, it seemed odd to me that I have a repository of articles (i.e. CraigWriter) that I edit once in a while that isn't in wiki form. After all, I've spent a large chunk of my free time in the last six months writing tools to make editing FlexWiki easier. So this weekend, while I was in Minnesota attending a wedding of a close friend, I found myself sitting around my parents' house with no broadband Internet. After recovering from email withdrawal, I decided it was a good time to port my content to the heretofore empty Pluralsight wiki.


And so I have! This change of technologies brings several benefits:



  1. It's easier for me to edit things in real time.

  2. I can ditch the hand-rolled code I wrote to support my articles.

  3. Other people can contribute more easily.

  4. The wiki has a series of RSS feeds so people can find out about changes and new articles.

  5. Since FlexWiki is open source, we get the benefit of any improvements the community makes, without having to wait for Craig to get free time.

I think I've got everything moved over except the translations of my Direct3D tutorial. Because they're not in English, it's a bit harder for me to make sure I got everything right, and I'm punting it for now. I do plan to move those as well, though, after I recover from being offline for four days. I'll also put up redirects for the existing repository before too long.


In the meantime, have a look at the new wiki and let me know if you see anything wrong, stupid, or broken.

Monday, July 12, 2004

NUnitAsp First Impressions: I Like It

I've been playing around with NUnitAsp for about 15 minutes now, and I already like it a lot. It gives the ability to make requests to an ASP.NET web page, and then easily verify that the contents of various server controls have rendered correctly. And it plugs into NUnit, so you get that same red/yellow/green display. I even managed to make it populate a login form with my credentials, click the submit button, and verify that it redirected me to the right page. Took about three minutes to write.


In addition to being useful for doing TDD of web apps, this is definitely something that should make writing build verification tests easier. Build verification tests (BVTs) are distinctly different from unit tests, in that they are intended to work against the system as a whole, rather than against a small piece of code. So as one of its last steps, the build script can copy the newly compiled web content to the file system, create a virtual directory, then use nunit-console to run tests that hit various pages, making sure everything works okay as deployed.

Sunday, July 11, 2004

Taking a Small Step to the Left

My blog has moved again! Only, not very far this time: instead of http://pluralsight.com/craig/ it now lives at http://pluralsight.com/blogs/craig/. The Pluralsight guys had to restructure the site a little to make things run more smoothly, and we figured better sooner than later. Everything should already be getting redirected automatically (including the RSS feed), but you can update your bookmarks and aggregators if you like. Please let me know if you find any broken links or missing content.


Also, apologies if your aggregator spewed a bunch of my old posts as new ones, but at least now you know why.

Thursday, July 8, 2004

XmlInclude - Not Quite as Useless as I Thought

Simon Horrell pointed something out to a bunch of us the other day that I thought was quite interesting. It has to do with the [XmlInclude()] attribute that's part of the System.Xml.Serialization stuff. Ordinarily, you use it on a base type to indicate that when serializing instances of that type, they might really be instances of one or more subtypes. This allows the serialization engine to emit a schema that reflects the possibility of really getting a Derived when the type signature is Base. For example, consider the following web service:

<%@ WebService class="Service" Language="C#" %>

public class Animal {
  public int legs;
}

public class Mammal : Animal {
  public int nipples;
}

public class Service {
  [WebMethod]
  public Animal GetAnimal() {
    return new Mammal();
  }
}

Note that GetAnimal is typed to return an Animal, but actually returns a Mammal. Well, if you were to look at the XML that came back from this method, you might be surprised to see that it looks like this:

<Animal>
  <legs>8</legs>
</Animal>

You'll observe that this result does not contain any mention of nipples - the “Mammalness” has been lost. Which makes sense - from an XML standpoint, you told me that the operation returns a type that just has legs.

One way we can “fix” this to give a result more in keeping with our OO expectations is to use the XmlInclude attribute on the base type, to list all the types that we might wind up substituting. It looks like this:

[System.Xml.Serialization.XmlInclude(typeof(Mammal))]
public class Animal {
  public int legs;
}

And if we run our web service now, we get this XML back:

<Animal xsi:type="Mammal">
  <legs>2</legs>
  <nipples>3</nipples>
</Animal>

Note the presence of the xsi:type attribute, which says, “This thing is actually a Mammal.” If you're generating a .NET proxy using VS.NET's Add Web Reference or the wsdl.exe command line tool, you'll even find that when you check the type of the object that comes back from the web service call, it's a Mammal, which derives from Animal. This is possible because in the schema for the web service, there's a bit that says that a Mammal is an extension (an XML schema term) of Animal.

If you're an OO person, however, you probably don't like the fact that you have to hang that XmlInclude attribute off the base type. The idea that a base type has to know about its derived types in advance is, well, just plain weird. This is where Simon comes in. He pointed out that you can actually put the XmlInclude attribute on the method instead of the base type. So if we change our web service to look like this instead:

<%@ WebService class="Service" Language="C#" %>

public class Animal {
  public int legs;
}

public class Mammal : Animal {
  public int nipples;
}

public class Service {
  [System.Web.Services.WebMethod]
  [System.Xml.Serialization.XmlInclude(typeof(Mammal))]
  public Animal GetAnimal() {
    return new Mammal();
  }
}

We'll get the same result (i.e. it'll have legs and nipples and use the xsi:type attribute) as putting the attribute on the Animal type. But putting it on the method is much more attractive from a code point of view, since it doesn't bake assumptions about type derivation into the base type. Rather, you put them on the method, where you probably have a good idea about what exact types are being returned.

Now, that said, I wouldn't write web services using this. Why not? Because if you care about interoperability, writing schemas that make use of extension elements and xsi:type isn't exactly “polite“. You don't know what technology your clients will be written in, and not all languages even have type derivation. Those that do, don't necessarily take the same view of it as C#. And even if they do, not all toolkits are smart enough yet to both map the XSD extension correctly and to look for the xsi:type attri

Wednesday, July 7, 2004

Busted

The wise Scott Hanselman and Richard Blewett both noted that my recent post about SoapParameterStyle.Bare was apparently at odds with Tim's post about the same thing. Well, they're right. The reason? My post was - to use the euphemistic engineering term for “lame“ - sub-optimal. But allow me to explain, hopefully clearing up any web service confusion that may have arisen.

Tim and I had had an interesting conversation one afternoon while I was at his place, in which he explained to me the pattern he describes in his post...of which SoapParameterStyle.Bare is an part, but only a part. More important is combining SoapParameterStyle.Bare with the style of using a single input and single output parameter - without this you don't realize all the benefits that Tim outlines in his excellent blog entry.

Anyway, when I posted, I didn't want to tell the whole story, because I was trying to goad Tim into blogging it, and didn't want to steal his punchline. But by only explaining half, the post wound up missing the point. I've updated my old post to point to Tim's stuff in the interest of community service. :)

Monday, July 5, 2004

Nice Explanation of Direct3D Frame Hierarchies

I get occasional emails from people that go something like, “Hey, I like your Direct3D Tutorial. When are you going to write more?“


D'oh! It's been months since I've written a new one, but between work at two clients, FlexWiki, moving the weblog, and all the other stuff going on, I just haven't had the time (although writing more is still on my list).


Luckily, others are not quite so lax. For instance, Joakim Karlsson has just posted a nice explanation of how to create and use a basic frame hierarchy. He's got another article on fullscreen device recovery, too, so here's hoping that he finds time to write more Direct3D stuff soon.

Sunday, July 4, 2004

dasblog2dottext Released

Peter and I did some work this weekend and got dasblog2dottext released! This is a very handy tool that Peter wrote; it imports all of your dasBlog content into a .Text instance, which is what made it easy for me to move my weblog here. Peter even wrote a little redirector that forwards all comment and permalink pages over to the appropriate entry on the new site.


What's funny is that I'm the one that wrote the BlogXToDasBlogImporter that's part of the dasBlog workspace. Hopefully I won't need to migrate to anything else for quite some time.


Anyway, the project is up on SourceForge...enjoy!

Friday, July 2, 2004

My New Home

If you're reading this, you're aware that I've moved CraigBlog to its new home here at Pluralsight. But why did I move? And why so suddenly?


Let me address the last point first: the move was only sudden from a public point of view. I wanted to throw the switch and have everything flip over to the new site as quickly as possible because I wanted to take all my posts - and the comments on those posts - with me. The longer the lag between the new site going live and the old one getting redirected over, the more information I was going to lose (or have to move manually). So I've actually been talking to the Pluralsight guys about this for weeks, and have spent a fair number of evenings and lunch hours getting it set up.


But back to "why". It's really simple, actually: because I think the Pluralsight guys are an absolutely top-notch group of dudes (as well as being good friends), and hanging out with them in virtuality seemed like it would be fun. They've got an exciting new company going and history, if nothing else, would indicate that they're going to be producing some excellent stuff. When they asked me if I'd be interested in coming over, I figured that if I can help them out by bringing some more traffic their way, I was happy to do it.


Oh, and as a consultant who lives by his reputation, it doesn't hurt me at all to hang my blog shingle up next to names like Aaron Skonnard, Don Box, Fritz Onion, Keith Brown, Mike Woodring, and Tim Ewald. :)


I'd like to thank Fritz and Keith in particular for handling their side the transition of CraigBlog - I've got a fair amount of content, and I had some requirements that they had to run around a bit to meet. I'd also like to think Peter Provost, who wrote the excellent dasBlog2dotText conversion tool, which is what made it possible for me to port all my content in a few hours rather than a few months. He and I are going to be releasing the tool on SourceForge this weekend - I'll be sure to let you know here (at my comfy new home on the web) when it's ready.