Archive for March, 2010

Windows Phone DevCamp: Chicago, April 10

This is a DevCamp. In the morning, we’ll get an overview of how to use the toolchain. After that, we eat and build a number of kick-ass applications on Windows Phone 7 emulators.

That’s it. Just devs in a room learning about Windows Phone 7.

Tentative Schedule:

8:30- Checkin

9:30-12:00 Presentation on Windows Phone 7 and how to develop on it

12:00 Lunch

1:00-5:00 Attendees build apps

5:00-6:00 Judge apps

6:00-6:30 Hand out awards

6:30 event is over, go home.

I look forward to meeting you. See you there!

Events

Leave a comment

Silverlight Printing

I have had a project on my “I should build that” list for several years. I do volunteer work with the Racine/Kenosha Wisconsin Friends of the NRA. Every year, we (and many other FNRA groups across the USA) host an event that raises money to support the shooting sports community in Wisconsin. This money funds range improvements, youth hunting programs, events for veterans, and other things the local shooting sports community needs. Part of the fund raising is a raffle we do every year. To run the raffle, we print the tickets early and sell them in the months leading up to our big banquet in October. The ticket printing gig fell to me since I grabbed the job.

For the past 2 years, I handled this job by printing the tickets from an Excel spreadsheet. I laid things out just so and was able to rifle through all the tickets, one page at a time, in about 90 minutes. I regularly messed up several sheets during  the printing because I would miss a number here or there. I looked at applications to print the tickets and thought “That looks easy. I should just build that.” 2010 printing season arrived and I finally did. Given that Silverlight now supports printing and I hadn’t tried anything interesting in printing reports with it, yet, I decided to build an Internet capable application to support my needs.

A few words first: this application supports my needs for tickets and mine alone. I needed to print a raffle ticket that had the following characteristics:

1. Prints to an 8.5″ x 11″ piece of paper.

2. Has 8 tickets per page.

3. Has the perforations where my sheets had perforations.

4. Prints a specific header for each stub.

5. Prints a user customized description to each ticket body.

6. Handles multipage printing.

This code is guaranteed to work on a Canon MP780 printer, because that is what I own. YMMV if you own a different printer. The app looks like this:

image

While printing these tickets, I found a the program refuses to handle documents larger than 34 pages or 272 tickets. This seems to be limited because Silverlight printing generates bitmaps which tend to be space intensive. At 34 pages, I’m seeing the print spool show 2GB+ of memory for the spooled job. My print server is a 32-bit Windows Home Server box-a 64-bit machine may do better.

The code

Adding a print handler to Silverlight is pretty easy. You need to make sure that printing is initiated from a user action with no other UI intervening in between the button click and the presentation of the print dialog. For example, you can’t add a MessageBox.Show(“Hi”) in between the button click and the creation of the print job. To handle the printing, you just need to create a System.Windows.Printing.PrintDocument, hook the PrintPage event, and go.

private void Button_Click(object sender, RoutedEventArgs e)
{
    var doc = new PrintDocument();
    var ticket = (Ticket) LayoutRoot.DataContext;
    var pageStart = ticket.FirstTicket;

    doc.PrintPage +=
        (s, eventArgs) =>
            {
                eventArgs.HasMorePages = (pageStart + 8) < ticket.LastTicket;
                eventArgs.PageVisual = GeneratePage(ticket, pageStart, eventArgs);
                pageStart += 8;
            };
    doc.Print("Tickets");
}

PrintPage passes a sender object and a PrintPageEventArgs instance to the event handler. PrintPageEventArgs has two propertiees that are important: HasMorePages and PageVisual. Set HasMorePages to true if the PrintPage event should be called again. If the code is printing the last page, set HasMorePages to false. The PageVisual property tells the runtime what should be printed. Any valid descendent of UIElement works here.

While doing this printing, I tried a few approaches before finding one that worked.Please note that I stopped writing code as soon as this thing worked. I first tried creating the entire page of tickets via code and no XAML assistance. Setting up the tickets went pretty well. I had a number of issues putting the exact correct transform on the ticket description so that it would rotate 90 degrees and appear in the right spot on each ticket. I was regularly off by a fraction of an inch on one ticket or another. After futzing with this for an hour, I tried setting up the entire page. This got to be hard because the data binding code and little adjustments were killing a lot of time. I believe I could have made either approach work eventually, but I wasn’t that interested in the puzzle to go that far.

My final solution was a combination of all in code and all in XAML: I designed a user control called ticket. You can see the ticket user control in the screen shot above. This had a few advantages:

1. I was able to add WYSIWYG display of the tickets to the user, so that surprises are minimized when printing tickets.

2. I could get the orientation of the bound data perfect in Expression Blend.

3. This was up and running in about 15 minutes from the time I started designing the ticket until it worked as a printout.

The layout code is handled by GeneratePage. I used StackPanels to hold the tickets and simplify the layout calculations. I used data binding to set the ticket numbers and ticket text. The one tricky part of the layout was taking account of the left and right margins. The tickets don’t change size, but the print area does for the tickets on the left and right side of  the page. You’ll see that for columns 0 and 3, the code handles the edges. You’ll also notice that the following code is single purpose-it only works for my ticket sheet.

private static UIElement GeneratePage(Ticket ticket, int pageStart,
    PrintPageEventArgs args)
{
    double gridHeight = args.PrintableArea.Height;
    double gridWidth = args.PrintableArea.Width + args.PageMargins.Left +
        args.PageMargins.Right;
    var retval = new StackPanel
                     {
                         Height = gridHeight,
                         Width = gridWidth,
                         Orientation = Orientation.Vertical
                     };
    for (var i = 0; i < 2; ++i)
    {
        // Add a StackPanel that has Horizontal layout
        var rowPanel = new StackPanel
                           {
                                Height = gridHeight/2,
                                Width = args.PrintableArea.Width,
                                Orientation = Orientation.Horizontal
                           };
        retval.Children.Add(rowPanel);
        // Add columns
        for (var j = 0; j < 4; ++j)
        {
            if (pageStart > ticket.LastTicket)
            {
                break;
            }
            var stackPanel = new StackPanel
                                 {
                                     Orientation = Orientation.Vertical,
                                     Height=rowPanel.Height,
                                 };
            rowPanel.Children.Add(stackPanel);
            switch (j)
            {
                case 0:
                    stackPanel.Width = gridWidth/4 - args.PageMargins.Left;
                    break;
                case 3:
                    stackPanel.Width = gridWidth/4 - args.PageMargins.Right;
                    break;
                default:
                    stackPanel.Width = gridWidth/4;
                    break;
            }
            var ticketControl =
                new TicketControl
                    {
                    LayoutRoot =
                        {
                            DataContext = new SimpleTicket
                            {
                                Text = ticket.TicketText,
                                TicketLabel = string.Format("No. {0:000}", 
                                     pageStart)
                            }
                         }
                    };
            stackPanel.Children.Add(ticketControl);
            ++pageStart;
        }
    }

    return retval;
}

Yes, I realize I could have bought their software for $30 and saved myself the time of writing this application. But, I wanted to learn how to use the print functionality in Silverlight, and $30 would not have taught me the stuff I learned by doing.

If you want to try out the application, I’ve put it up over here. Source code (Silverlight 4.0 RC) is here. Have fun!

Leave a comment

Review of RedGate .NET Reflector Pro

Disclaimer: RedGate is a sponsor of devlicio.us and offered a copy of the product and a ThinkGeek gift certificate as an incentive to review their product. This review is the work of the author and was not approved by anyone other than the author. There, now you know the kind of taint this review has. Please keep reading anyhow. OK? Good!

.NET Reflector is part of any respectable .NET developer’s tool belt. When you want to figure out how something works, why your code breaks when interacting with some library, you view the assembly through .NET Reflector’s lens. The latest version, 6.1.0.11, will display the IL in an assembly as IL, Managed C++, VB.NET, C#, Delphi, or Oxygene. The latest version has been updated to support .NET 4 and allows you to jump into .NET Reflector from Visual Studio. I was disappointed to see that the “Open in .NET Reflector” menu option is only available from the Object Explorer. I would have expected to see this option by right-clicking on the assembly from the References list in the Solution Explorer, but no. Given that other tools (TestDriven.NET in particular) do add this functionality (they actually add “Open in .NET Reflector” from the Solution Explorer!) RedGate needs to address this usability issue.

Otherwise, the free version of .NET Reflector hasn’t changed. It is still a great tool.

So, what about this new, Pro version? First, it costs $195 US. What do you get for that price? You get the ability to generate source code and PDBs so that you can step through the assemblies you use in the languages you know. If you are debugging Microsoft provided assemblies, you can already step through assemblies using the actual source (typically C#) through the Enable .NET Framework Source Stepping option from the Options dialog (in VS 2008/2010, access this dialog from Tools->Options menu.)

image

In the past, Microsoft wasn’t always good about keeping their symbol servers and source code servers up to date. Not every group put their code into the repository right away, so service packs and other patches might cause you to lose the ability to step through code. If you use components from other vendors, this option does you no good at all. RedGate is betting that a number of you want to be able to step through all .NET assemblies in VB.NET or C#. At a high level, RedGate generates the source code for an entire assembly and dumps it onto disk. It also writes out a PDB that tells Visual Studio how to map the assembly code to the generated code.

To long time users of .NET Reflector, the code generation piece may sound like old hat. It is. Back in May of 2004, Denis Bauer released a .NET Reflector plug-in that dumps the assembly information as code files (the plug-in was last updated for .NET Reflector v5). If you want a full project file for the dumped files, you used Jason Bock‘s FileGenerator plugin. Unfortunately, neither of these allow you to step through code, and that’s what many of us need. .NET Reflector Pro adds that functionality.

The overall experience is seamless. Upon running .NET Reflector, the .NET Reflector top level menu is added to Visual Studio 2008/2010. From here, you can either decompile an assembly in your project, Explore Decompiled Assemblies, or Debug an Executable.

Explore Decompiled Assemblies just pops open the Object Explorer in Visual Studio. I would have expected the list to be reduced to the list of assemblies I had already decompiled, but that isn’t what happened. Debug an Executable is a bit confusing too-it just fires up the executable and attached the debugger. If you have decompiled the assemblies of interest already, you can step through that code. Otherwise, this feature seems to be a bit of a waste. When PDB information does not exist, I would have expected the UI to say something like “.NET Reflector has not created debugging information for the selected executable. Would you like to generate source code and PDBs now?” I should then be able to select the assemblies I want to debug using this new functionality.

All that said, the tool does redeem itself. When selecting .NET Reflector->Choose Assemblies to Debug, the tool gets things right. This is the only feature in the Pro version that seems to have been completely thought out. At this stage, you are presented with the following dialog:

image

You can generate the source in C# v2.0/3.0 or Visual Basic 8.0/9.0. You then select the assemblies you would like to be able to step through and press OK. A little while later (time completely dependent on the size of the assembly), you are ready to do source level debugging. In the I tested out, this worked as advertised. I was able to step into System.dll, System.Web.dll, and other assemblies I regularly use. So, for .NET 4.0, clearly a win. F11 works fine, you can set breakpoints etc. For .NET 4.0 developers, this will be very helpful debugging those nasty issues where you need to figure out why your code is causing .NET and other libraries to die.

So, how about Silverlight? I had .NET Reflector generate the source/debug information for System.Windows. Then, I set a breakpoint in the constructor for my Silverlight MainPage.xaml.cs. I was able to step out to MS.Internal.CoreInvokeHandler.InvokeEventHandler.

image

I tried doing the same thing with the just released Windows Phone SDK. In this case, I was unable to get the application to rebuild correctly and work. After instructing .NET Reflector to generate the information for System.Windows for a Windows Phone Application, I saw this dialog:

image

After generating the assemblies, Reflector pointed the references in the solution to the new assemblies. Upon debugging, I saw this message (followed by several more for the other updated assemblies):

—————————

.NET Reflector
—————————
The loaded assembly "System.Windows" is not the one .NET Reflector expected.

Expected version: "c:tempregenSystem.Windows.dll"

Loaded version: "System.Windows.dll"

If the correct assembly is not loaded, debugging may not work.
—————————
OK  
—————————

If you are doing any Windows Phone development, the tool does not work for you. I imagine that this shortcoming will be addressed in the coming months-the SDK was only recently released.

Other things I noticed

The source code gets dropped into an AppData folder. For example, the code for MS.Internal.CoreInvokeHandler is at:

C:UsersScott SeelyAppDataLocalRed Gate.NET Reflector 6CacheV4x86CSV35c46bf0b4-91fb-4aa9-8732-63fe4e8d7afcMSInternalCoreInvokeHandler.cs

Looking in the v35 directory, we see that a PDB is dumped out:

imageThe assemblyLoc file corresponding to the System.Windows.PDB file has the following contents:

c:Program Files (x86)Reference AssembliesMicrosoftFrameworkSilverlightv4.0System.Windows.dll

For an assembly in the GAC, System.Windows.Forms, the assemblyLoc file points to it’s GAC location:

C:WindowsMicrosoft.NetassemblyGAC_MSILSystem.Windows.Formsv4.0_4.0.0.0__b77a5c561934e089System.Windows.Forms.dll

which appears to say that the symbols are generated from that particular reference assembly. The GUID named folder contains source code. 

Summary

Having access to source and single stepping helps me troubleshoot problems faster because I can see why the underlying code doesn’t like what I’m doing when consuming the class libraries. Like most developer tools, this one has its value in the time savings you will get by getting you to the why of a bug in less time. I like the tool because it doesn’t change how I do my day job. It gives me access to more code so I can poke down the debug path even further without pulling out Reflector to grok why my code isn’t behaving as expected. And, I can easily make stepping into other people’s code part of my daily workflow.

Overall, I like the enhancements and am looking forward to using .NET Reflector Pro.

Leave a comment

Versioning REST Services

I’ve always been intrigued by the versioning problem. The versioning problem works like this: you build an API (Application Programming Interface) to get some work done. That API is successful and consumers ask for enhancements to the API. At this point, you have a problem: how do you support everyone who uses the current API while adding enhancements? If you have been down this road, you know that you have to solve the problem early-before success.

The way you handle versioning varies. With compiled code and libraries, you send out a new DLL/Assembly/JAR file and tell folks to convert existing code when they have a chance. With Web services, including SOAP, REST, and just HTTP accessible ones, you have other issues. You typically want a single code base to consume the old and updated messages. Given that many of us are now writing REST services, I talked to InformIT about the need for an article explaining how to version these JSON/XML speaking endpoints. That article is now live and available for your reading at http://www.informit.com/articles/article.aspx?p=1566460.

Leave a comment

Back at Work

Friends and folks in the .NET community learned that I got hit pretty hard by the flu last week. I was hospitalized for 3 days while they made sure I didn’t break any other internal systems. I just wanted to let folks know that I’m back at work. The rest of the family has been hit by the flu as well, though not as hard as me (thank goodness!). I appreciated all the offers of help from folks around me.

Other questions: was this H1N1? I don’t know, but I did get the vaccine cocktail for everything but H1N1. You do the math-it was either H1N1 or something that I just couldn’t handle.

Why was I hospitalized? I was losing fluids for 12 hours straight. That scared me and I went to the doctor. He thought it might be appendicitis. I went to the hospital and they ruled out appendicitis and a few other diseases. I was held mostly because of the severe loss of fluids to make sure it was only the flu.

Again, thanks to everyone who offered help. It is appreciated!

Leave a comment

Follow

Get every new post delivered to your Inbox.