Dealing with Urls in books


Tonight I spent some time reviewing the latest batch of sample code for Volume 2 of the SLAR.  As you may recall, Volume 2 covers System.Xml, System.Net, System.Reflection namespaces (among others).  I really want every type and nearly every member in the book to have a real, compliable and run-able code sample that shows common usage. 

 

This poses a little bit of a problem for the System.Net samples.  Many of them need to refer to a working webserver and some of them require special behavior from that server.    I could just point these all at http://localhost, but I fear that would mean many of them would not run correctly on most customer’s machines unless they do some configuration. 

 

Thoughts on how to handle this? 

 

BTW – if you are interested in being a reviewer for Vol2, please let me know

 

Here are a couple of examples:

 

  public class EndPointSample

  {

    public static void Main()

    {

      IPAddress ip = IPAddress.Parse(“127.0.0.1”);

      IPEndPoint ep = new IPEndPoint(ip, 9999);

      Console.WriteLine(“EndPoint.AddressFamily = ‘{0}'”,

                        ep.AddressFamily.ToString());

      SocketAddress sktaddr = new

                    SocketAddress(AddressFamily.InterNetwork);

      EndPoint newep = (EndPoint)ep.Create(sktaddr);

      Console.WriteLine(“New EndPoint.AddressFamily = ‘{0}'”,

                        newep.AddressFamily.ToString());

    }

  }

 

  public class DnsSample

  {

    private static bool bDone = false;

 

    public static void Main()

    {

      String toFind = “microsoft.com”;

      IAsyncResult dummy = Dns.BeginResolve(toFind, new AsyncCallback(DnsCallback), null);

      while(!bDone) {}

    }

 

    private static void DnsCallback(IAsyncResult ar)

    {

      IPHostEntry host = Dns.EndResolve(ar);

      ShowHostDetails(host);

      bDone = true;

    }

 

    private static void ShowHostDetails(IPHostEntry host)

    {

      Console.WriteLine(“HostName = ‘{0}'”, host.HostName);

      foreach (IPAddress addr in host.AddressList)

      {

        Console.WriteLine(“IPAddress = {0}”, addr.ToString());

      }

      foreach (String alias in host.Aliases)

      {

        Console.WriteLine(“Alias = {0}”, alias);

      }

    }

 

  }

  public class HttpStatusCodeSample

  {

    public static void Main()

    {

      HttpWebRequest req = (HttpWebRequest)

                     WebRequest.Create(“http://localhost”);

      HttpWebResponse result = (HttpWebResponse)req.GetResponse();

      Console.WriteLine(“HttpWebResponse.StatusCode = {0}”,

                         result.StatusCode.ToString());

    }

  }

 

Comments (18)

  1. Todd says:

    For IP addresses, use one of the private IP blocks (10.x.x.x, 172.16.x.x, 192.168.x.x). The 192.168 block is probably the most used for private networks, so I’d stick with 172.16.x.x or pick something from 10.x.x.x that is unlikely to be used (10.150.x.x or something like that).

    For domain names, use one of the reserved example domain names at http://www.rfc-editor.org/rfc/rfc2606.txt.

    This is a problem that has bitten many companies, including Microsoft. Samples have used things like http://www.xxx.com (warning! pr0n link, obviously not work-safe) as example URLs, and later find out that it’s a porn site (or some entrepeneurial web developer found that the sample domain was unregistered, registered it, and put up some porn). Avoid this at all costs, and use the designated sample domains.

  2. RichB says:

    Ship a really simple webserver sample and then in your examples connect to that server on localhost

  3. Matthias Ernst says:

    private static bool bDone = false;



    while(!bDone) {}

    ….

    bDone = true;

    [Off topic] Your example is not good. The while loop does a busy wait and the "read" of bDone could actually be hoisted out of the loop so that it never terminates. Isn’t there a simple Event API you can use? While that is not the topic of your article, this is code people will copy.

  4. Nicholas Allen says:

    Instead of the busy wait, it could create a ManualResetEvent and use WaitOne to block.

  5. AT says:

    Matthias, I agree with you.

    Actualy dummy.AsyncWaitHandle.WaitOne(); (or WaitHandle.WaitAny/WaitAll in case if you need to use more that 1 request but less that 65) must be called instead of "while(!bDone) {}"

    I believe that publishing examples like this one must be allowed only to show/reveal common mistakes. Even if this is not a topic of article – "dummy.AsyncWaitHandle.WaitOne();" is pretty short and readable line.

    As well – using this line will allow to remove "private static bool bDone = false;" and "bDone = true;" lines.

    Additionaly – in HttpStatusCodeSample there are a lot of casts without any validation.

    For example think about this:

    class MyHack: IWebRequestCreate {

    public WebRequest Create(Uri uri) { return new FtpWebRequest(uri); }

    }

    WebRequest.RegisterPrefix("http://", new MyHack());

    As result WebRequest.Create("http://localhost"“>http://localhost"); will not return HttpWebRequest

    Or less tricky situation – instead of "http://localhost"“>http://localhost" – user will pass "ftp://localhost".

    There is useless cast in EndPointSample

    EndPoint newep = (EndPoint)ep.Create(sktaddr);

    ep.Create already return EndPoint. No needs to cast once more 😉

    I believe this cast is an artifact from IPEndPoint -> EndPoint edit.

  6. David Levitt says:

    My suggestion is have a separate appendix item that has instructions to configure the webserver that is referenced in the chapters. Then have a disclaimer in the introduction that explains that any code samples are written assuming that the reader has configured their webserver per the instructions in Appendix <insert letter>.

    I think that would be the easiest way to handle the issue….

  7. Erik Sargent says:

    I agree with the appendix, but one suggestion might be to have a configuration test program to make sure that not only a web server exists but also that the mail server is turned on, FTP and anything else you need. Just a simple winforms app that checks to make sure they all exist and have the right permissions. It shouldn’t be nearly as complex as it sounds.

  8. The trouble is, you probably need more than a web server for demonstrating other protocols etc.. And depending on what you are trying to do, going out to another server may run into firewalls.

    So the best thing would be: 1) write a program that tests the user’s machine and lets her know what will and won’t run, why, and what needs to be done to fix it; 2) maintain a public server for this book, or list suggestions of what server out there provides the needed functionality; 3) include a simple web server for testing (Webmatrix?).

    To make all this easier, add a simple program that pops up a dialog to configure all this. Then read the host name you need and whatnot from a configuration file created by this program.

    Asking people to install all kinds of services for this book is a no starter. One, it’s difficult; two, it opens up all kinds of potential holes; and three, it probably requires expensive software that’s only included with Windows Server. So if you do include a web server, or a simple pop server etc., make it a program the user can start for experimenting, but that exits immediately upon logout.

  9. Point to http://localhost and provide a Windows Installer package on CD or Website that would setup the web server (or machine) as necessary.

    I’m interested in being a reviewer for Vol2.

  10. Larry SMith says:

    Re while(!bDone):

    Strictly speaking, all the comments about mutexes and the like are using elephant guns against fleas. bDone should be declared volatile.